Index: src/platform-linux.cc |
diff --git a/src/platform-linux.cc b/src/platform-linux.cc |
index 6ec5070f911c787973b838bc28d549ca5c29a730..cb93afbdff909c0098542cce971df5c4bb786054 100644 |
--- a/src/platform-linux.cc |
+++ b/src/platform-linux.cc |
@@ -56,6 +56,8 @@ |
#include "v8.h" |
#include "platform.h" |
+#include "top.h" |
+#include "v8threads.h" |
namespace v8 { |
@@ -580,6 +582,7 @@ Semaphore* OS::CreateSemaphore(int count) { |
#ifdef ENABLE_LOGGING_AND_PROFILING |
static Sampler* active_sampler_ = NULL; |
+static pthread_t vm_thread_ = 0; |
#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) |
@@ -608,6 +611,30 @@ enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11}; |
#endif |
+// A function that determines if a signal handler is called in the context |
+// of a VM thread. |
+// |
+// The problem is that SIGPROF signal can be delivered to an arbitrary thread |
+// (see http://code.google.com/p/google-perftools/issues/detail?id=106#c2) |
+// So, if the signal is being handled in the context of a non-VM thread, |
+// it means that the VM thread is running, and trying to sample its stack can |
+// cause a crash. |
+static inline bool IsVmThread() { |
+ // In the case of a single VM thread, this check is enough. |
+ if (pthread_equal(pthread_self(), vm_thread_)) return true; |
+ // If there are multiple threads that use VM, they must have a thread id |
+ // stored in TLS. To verify that the thread is really executing VM, |
+ // we check Top's data. Having that ThreadManager::RestoreThread first |
+ // restores ThreadLocalTop from TLS, and only then erases the TLS value, |
+ // reading Top::thread_id() should not be affected by races. |
+ if (ThreadManager::HasId() && !ThreadManager::IsArchived() && |
+ ThreadManager::CurrentId() == Top::thread_id()) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { |
USE(info); |
if (signal != SIGPROF) return; |
@@ -640,7 +667,8 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { |
sample.fp = mcontext.arm_fp; |
#endif |
#endif |
- active_sampler_->SampleStack(&sample); |
+ if (IsVmThread()) |
+ active_sampler_->SampleStack(&sample); |
} |
// We always sample the VM state. |
@@ -678,6 +706,8 @@ void Sampler::Start() { |
// platforms. |
if (active_sampler_ != NULL) return; |
+ vm_thread_ = pthread_self(); |
+ |
// Request profiling signals. |
struct sigaction sa; |
sa.sa_sigaction = ProfilerSignalHandler; |
@@ -713,6 +743,7 @@ void Sampler::Stop() { |
active_ = false; |
} |
+ |
#endif // ENABLE_LOGGING_AND_PROFILING |
} } // namespace v8::internal |