Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: src/platform-linux.cc

Issue 171115: Linux profiler: check whether signal handler is called in the VM thread. (Closed)
Patch Set: Now dealing with multiple threads correctly, added test. Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/v8threads.h » ('j') | src/v8threads.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « no previous file | src/v8threads.h » ('j') | src/v8threads.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698