Fix race in VerifyStackReadWithMultipleThreads

Patch by Chris Dearman <chris@mips.com>
R=ted at http://breakpad.appspot.com/377002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@959 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
ted.mielczarek 2012-04-25 11:42:52 +00:00
parent e8dbecb42c
commit e6e778f635
2 changed files with 28 additions and 19 deletions

View File

@ -51,7 +51,14 @@
#endif
void *thread_function(void *data) {
int pipefd = *static_cast<int *>(data);
volatile pid_t thread_id = syscall(__NR_gettid);
// Signal parent that a thread has started.
uint8_t byte = 1;
if (write(pipefd, &byte, sizeof(byte)) != sizeof(byte)) {
perror("ERROR: parent notification failed");
return NULL;
}
register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = &thread_id;
while (true)
asm volatile ("" : : "r" (thread_id_ptr));
@ -75,14 +82,8 @@ int main(int argc, char *argv[]) {
pthread_attr_init(&thread_attributes);
pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
for (int i = 1; i < num_threads; i++) {
pthread_create(&threads[i], &thread_attributes, &thread_function, NULL);
pthread_create(&threads[i], &thread_attributes, &thread_function, &pipefd);
}
// Signal parent that this process has started all threads.
uint8_t byte = 1;
if (write(pipefd, &byte, sizeof(byte)) != sizeof(byte)) {
perror("ERROR: parent notification failed");
return 1;
}
thread_function(NULL);
thread_function(&pipefd);
return 0;
}

View File

@ -212,7 +212,9 @@ TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
exit(0);
}
close(fds[1]);
// Wait for the child process to signal that it's ready.
// Wait for all child threads to indicate that they have started
for (int threads = 0; threads < kNumberOfThreadsInHelperProgram; threads++) {
struct pollfd pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.fd = fds[0];
@ -222,10 +224,16 @@ TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) {
ASSERT_EQ(1, r);
ASSERT_TRUE(pfd.revents & POLLIN);
uint8_t junk;
read(fds[0], &junk, sizeof(junk));
ASSERT_EQ(read(fds[0], &junk, sizeof(junk)), sizeof(junk));
}
close(fds[0]);
// Child is ready now.
// There is a race here because we may stop a child thread before
// it is actually running the busy loop. Empirically this sleep
// is sufficient to avoid the race.
usleep(100000);
// Children are ready now.
LinuxPtraceDumper dumper(child_pid);
ASSERT_TRUE(dumper.Init());
EXPECT_EQ((size_t)kNumberOfThreadsInHelperProgram, dumper.threads().size());