mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-01-05 17:05:33 +00:00
Skip ElfCoreDumpTest.ValidCoreFile test if no core dump is generated.
CrashGenerator::CreateChildCrash() may have some flakiness. This patch changes ElfCoreDumpTest to temporarily skip the ValidCoreFile test if no core dump is generated by CrashGenerator::CreateChildCrash(), but print out the error message to help debug the flakiness. BUG=chromium-os:24982 TEST=Tested the following: 1. Build on 32-bit and 64-bit Linux with gcc 4.6. 2. All unit tests pass. Review URL: http://breakpad.appspot.com/342001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@904 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
03c31f2100
commit
3822e36b20
|
@ -130,15 +130,22 @@ TEST(ElfCoreDumpTest, TestElfHeader) {
|
||||||
TEST(ElfCoreDumpTest, ValidCoreFile) {
|
TEST(ElfCoreDumpTest, ValidCoreFile) {
|
||||||
CrashGenerator crash_generator;
|
CrashGenerator crash_generator;
|
||||||
if (!crash_generator.HasDefaultCorePattern()) {
|
if (!crash_generator.HasDefaultCorePattern()) {
|
||||||
fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped");
|
fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped "
|
||||||
|
"due to non-default core pattern");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned kNumOfThreads = 3;
|
const unsigned kNumOfThreads = 3;
|
||||||
const unsigned kCrashThread = 1;
|
const unsigned kCrashThread = 1;
|
||||||
const int kCrashSignal = SIGABRT;
|
const int kCrashSignal = SIGABRT;
|
||||||
ASSERT_TRUE(crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread,
|
// TODO(benchan): Revert to use ASSERT_TRUE once the flakiness in
|
||||||
kCrashSignal));
|
// CrashGenerator is identified and fixed.
|
||||||
|
if (!crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread,
|
||||||
|
kCrashSignal)) {
|
||||||
|
fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped "
|
||||||
|
"due to no core dump generated");
|
||||||
|
return;
|
||||||
|
}
|
||||||
pid_t expected_crash_thread_id = crash_generator.GetThreadId(kCrashThread);
|
pid_t expected_crash_thread_id = crash_generator.GetThreadId(kCrashThread);
|
||||||
set<pid_t> expected_thread_ids;
|
set<pid_t> expected_thread_ids;
|
||||||
for (unsigned i = 0; i < kNumOfThreads; ++i) {
|
for (unsigned i = 0; i < kNumOfThreads; ++i) {
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
@ -108,8 +109,10 @@ bool CrashGenerator::MapSharedMemory(size_t memory_size) {
|
||||||
|
|
||||||
void* mapped_memory = mmap(0, memory_size, PROT_READ | PROT_WRITE,
|
void* mapped_memory = mmap(0, memory_size, PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||||
if (mapped_memory == MAP_FAILED)
|
if (mapped_memory == MAP_FAILED) {
|
||||||
|
perror("CrashGenerator: Failed to map shared memory");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
memset(mapped_memory, 0, memory_size);
|
memset(mapped_memory, 0, memory_size);
|
||||||
shared_memory_ = mapped_memory;
|
shared_memory_ = mapped_memory;
|
||||||
|
@ -126,12 +129,18 @@ bool CrashGenerator::UnmapSharedMemory() {
|
||||||
shared_memory_size_ = 0;
|
shared_memory_size_ = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
perror("CrashGenerator: Failed to unmap shared memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CrashGenerator::SetCoreFileSizeLimit(rlim_t limit) const {
|
bool CrashGenerator::SetCoreFileSizeLimit(rlim_t limit) const {
|
||||||
struct rlimit limits = { limit, limit };
|
struct rlimit limits = { limit, limit };
|
||||||
return setrlimit(RLIMIT_CORE, &limits) == 0;
|
if (setrlimit(RLIMIT_CORE, &limits) == -1) {
|
||||||
|
perror("CrashGenerator: Failed to set core file size limit");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CrashGenerator::CreateChildCrash(
|
bool CrashGenerator::CreateChildCrash(
|
||||||
|
@ -144,19 +153,31 @@ bool CrashGenerator::CreateChildCrash(
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
if (chdir(temp_dir_.path().c_str()) == 0 &&
|
if (chdir(temp_dir_.path().c_str()) == -1) {
|
||||||
SetCoreFileSizeLimit(kCoreSizeLimit)) {
|
perror("CrashGenerator: Failed to change directory");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (SetCoreFileSizeLimit(kCoreSizeLimit)) {
|
||||||
CreateThreadsInChildProcess(num_threads);
|
CreateThreadsInChildProcess(num_threads);
|
||||||
kill(*GetThreadIdPointer(crash_thread), crash_signal);
|
if (kill(*GetThreadIdPointer(crash_thread), crash_signal) == -1) {
|
||||||
|
perror("CrashGenerator: Failed to kill thread by signal");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
|
} else if (pid == -1) {
|
||||||
|
perror("CrashGenerator: Failed to create child process");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
if (HANDLE_EINTR(waitpid(pid, &status, 0)) == -1 ||
|
if (HANDLE_EINTR(waitpid(pid, &status, 0)) == -1) {
|
||||||
!WIFSIGNALED(status) || WTERMSIG(status) != crash_signal)
|
perror("CrashGenerator: Failed to wait for child process");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
if (!WIFSIGNALED(status) || WTERMSIG(status) != crash_signal) {
|
||||||
|
perror("CrashGenerator: Child process not killed by the expected signal");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,11 +197,13 @@ void CrashGenerator::CreateThreadsInChildProcess(unsigned num_threads) {
|
||||||
if (pthread_attr_init(&thread_attributes) != 0 ||
|
if (pthread_attr_init(&thread_attributes) != 0 ||
|
||||||
pthread_attr_setdetachstate(&thread_attributes,
|
pthread_attr_setdetachstate(&thread_attributes,
|
||||||
PTHREAD_CREATE_DETACHED) != 0) {
|
PTHREAD_CREATE_DETACHED) != 0) {
|
||||||
|
fprintf(stderr, "CrashGenerator: Failed to initialize thread attribute\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_barrier_t thread_barrier;
|
pthread_barrier_t thread_barrier;
|
||||||
if (pthread_barrier_init(&thread_barrier, NULL, num_threads) != 0) {
|
if (pthread_barrier_init(&thread_barrier, NULL, num_threads) != 0) {
|
||||||
|
fprintf(stderr, "CrashGenerator: Failed to initialize thread barrier\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,12 +212,14 @@ void CrashGenerator::CreateThreadsInChildProcess(unsigned num_threads) {
|
||||||
thread_data[i].thread_id_ptr = GetThreadIdPointer(i);
|
thread_data[i].thread_id_ptr = GetThreadIdPointer(i);
|
||||||
if (pthread_create(&thread_data[i].thread, &thread_attributes,
|
if (pthread_create(&thread_data[i].thread, &thread_attributes,
|
||||||
thread_function, &thread_data[i]) != 0) {
|
thread_function, &thread_data[i]) != 0) {
|
||||||
|
fprintf(stderr, "CrashGenerator: Failed to create thread %d\n", i);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = pthread_barrier_wait(&thread_barrier);
|
int result = pthread_barrier_wait(&thread_barrier);
|
||||||
if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) {
|
if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) {
|
||||||
|
fprintf(stderr, "CrashGenerator: Failed to wait for thread barrier\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue