diff options
-rw-r--r-- | src/maybe_threads.cc | 2 | ||||
-rw-r--r-- | src/profile-handler.cc | 5 | ||||
-rw-r--r-- | src/symbolize.cc | 42 | ||||
-rw-r--r-- | src/tcmalloc.cc | 1 |
4 files changed, 36 insertions, 14 deletions
diff --git a/src/maybe_threads.cc b/src/maybe_threads.cc index 6b7d7b9..cda1d63 100644 --- a/src/maybe_threads.cc +++ b/src/maybe_threads.cc @@ -63,7 +63,7 @@ extern "C" { int pthread_setspecific(pthread_key_t, const void*) __THROW ATTRIBUTE_WEAK; int pthread_once(pthread_once_t *, void (*)(void)) - __THROW ATTRIBUTE_WEAK; + ATTRIBUTE_WEAK; } #define MAX_PERTHREAD_VALS 16 diff --git a/src/profile-handler.cc b/src/profile-handler.cc index cf65740..1946f7c 100644 --- a/src/profile-handler.cc +++ b/src/profile-handler.cc @@ -215,11 +215,8 @@ const int32 ProfileHandler::kDefaultFrequency; // pthread_once won't be defined. We declare it here, for that // case (with weak linkage) which will cause the non-definition to // resolve to NULL. We can then check for NULL or not in Instance. -#ifndef __THROW // I guess we're not on a glibc system -# define __THROW // __THROW is just an optimization, so ok to make it "" -#endif extern "C" int pthread_once(pthread_once_t *, void (*)(void)) - __THROW ATTRIBUTE_WEAK; + ATTRIBUTE_WEAK; void ProfileHandler::Init() { instance_ = new ProfileHandler(); diff --git a/src/symbolize.cc b/src/symbolize.cc index 9dd890e..ff45e3e 100644 --- a/src/symbolize.cc +++ b/src/symbolize.cc @@ -87,16 +87,40 @@ int SymbolTable::Symbolize() { #else // All this work is to do two-way communication. ugh. extern char* program_invocation_name; // gcc provides this - int child_in[2]; // file descriptors - int child_out[2]; // for now, we don't worry about child_err - if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_in) == -1) { - return 0; - } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_out) == -1) { - close(child_in[0]); - close(child_in[1]); - return 0; + int *child_in = NULL; // file descriptors + int *child_out = NULL; // for now, we don't worry about child_err + int child_fds[5][2]; // socketpair may be called up to five times below + + // The client program may close its stdin and/or stdout and/or stderr + // thus allowing socketpair to reuse file descriptors 0, 1 or 2. + // In this case the communication between the forked processes may be broken + // if either the parent or the child tries to close or duplicate these + // descriptors. The loop below produces two pairs of file descriptors, each + // greater than 2 (stderr). + for (int i = 0; i < 5; i++) { + if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_fds[i]) == -1) { + for (int j = 0; j < i; j++) { + close(child_fds[j][0]); + close(child_fds[j][1]); + return 0; + } + } else { + if ((child_fds[i][0] > 2) && (child_fds[i][1] > 2)) { + if (child_in == NULL) { + child_in = child_fds[i]; + } else { + child_out = child_fds[i]; + for (int j = 0; j < i; j++) { + if (child_fds[j] == child_in) continue; + close(child_fds[j][0]); + close(child_fds[j][1]); + } + break; + } + } + } } + switch (fork()) { case -1: { // error close(child_in[0]); diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc index c288139..122e18f 100644 --- a/src/tcmalloc.cc +++ b/src/tcmalloc.cc @@ -898,6 +898,7 @@ inline bool should_report_large(Length num_pages) { return true; } return false; +} // Helper for do_malloc(). inline void* do_malloc_pages(ThreadCache* heap, size_t size) { |