| 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
|
|
|