summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/maybe_threads.cc2
-rw-r--r--src/profile-handler.cc5
-rw-r--r--src/symbolize.cc42
-rw-r--r--src/tcmalloc.cc1
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) {