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

Unified Diff: src/platform-linux.cc

Issue 11195045: Pass the SIGPROF signal on to previously registered signal handler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add newlines. Created 8 years 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 | no next file » | no next file with comments »
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 ec48d6305e3de2ea4b51f0571a1c7a83bb0ae619..aebcd083af55a0373970ee387ef6ffa57a34ba45 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -1022,62 +1022,6 @@ static int GetThreadID() {
}
-static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
- USE(info);
- if (signal != SIGPROF) return;
- Isolate* isolate = Isolate::UncheckedCurrent();
- if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
- // We require a fully initialized and entered isolate.
- return;
- }
- if (v8::Locker::IsActive() &&
- !isolate->thread_manager()->IsLockedByCurrentThread()) {
- return;
- }
-
- Sampler* sampler = isolate->logger()->sampler();
- if (sampler == NULL || !sampler->IsActive()) return;
-
- TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
- if (sample == NULL) sample = &sample_obj;
-
- // Extracting the sample from the context is extremely machine dependent.
- ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
- mcontext_t& mcontext = ucontext->uc_mcontext;
- sample->state = isolate->current_vm_state();
-#if V8_HOST_ARCH_IA32
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
-#elif V8_HOST_ARCH_X64
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
-#elif V8_HOST_ARCH_ARM
-#if defined(__GLIBC__) && !defined(__UCLIBC__) && \
- (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
- // Old GLibc ARM versions used a gregs[] array to access the register
- // values from mcontext_t.
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
-#else
- sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
- sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
- sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
-#endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
- // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
-#elif V8_HOST_ARCH_MIPS
- sample->pc = reinterpret_cast<Address>(mcontext.pc);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
-#endif // V8_HOST_ARCH_*
- sampler->SampleStack(sample);
- sampler->Tick(sample);
-}
-
-
class Sampler::PlatformData : public Malloced {
public:
PlatformData() : vm_tid_(GetThreadID()) {}
@@ -1089,6 +1033,9 @@ class Sampler::PlatformData : public Malloced {
};
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context);
+
+
class SignalSender : public Thread {
public:
enum SleepInterval {
@@ -1110,6 +1057,10 @@ class SignalSender : public Thread {
struct sigaction sa;
sa.sa_sigaction = ProfilerSignalHandler;
sigemptyset(&sa.sa_mask);
+ sigset_t signals_to_unblock;
+ sigemptyset(&signals_to_unblock);
+ sigaddset(&signals_to_unblock, SIGPROF);
+ sigprocmask(SIG_UNBLOCK, &signals_to_unblock, &old_signal_mask_);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
signal_handler_installed_ =
(sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
@@ -1118,10 +1069,33 @@ class SignalSender : public Thread {
static void RestoreSignalHandler() {
if (signal_handler_installed_) {
sigaction(SIGPROF, &old_signal_handler_, 0);
+ sigprocmask(SIG_SETMASK, &old_signal_mask_, NULL);
signal_handler_installed_ = false;
}
}
+ static void CallOldSignalHandler(int signal, siginfo_t* info, void* context) {
+ // Only invoke the old signal handler if it did not have SIGPROF masked.
+ if (sigismember(&old_signal_mask_, SIGPROF))
+ return;
+ if (!(old_signal_handler_.sa_flags & SA_SIGINFO)) {
+ // If the old signal disposition was SIG_IGN, then it is safe to ignore
+ // the old signal handler. If it is SIG_DFL, then that is pretty strong
+ // evidence that nobody other than us is using the profiling
+ // infrastructure. It is probably reasonable to assume that in this case
+ // we don't need to chain to the old behavior, as that would merely result
+ // in the application getting terminated.
+ if (old_signal_handler_.sa_handler == SIG_IGN ||
+ old_signal_handler_.sa_handler == SIG_DFL) {
+ return;
+ }
+ // Sorry, we only support other 3-arg signal handlers (sigaction). Crash
+ // loudly if someone tries to use a different signal handler.
+ *(reinterpret_cast<volatile char*>(NULL) + 74) = 0x34;
+ }
+ old_signal_handler_.sa_sigaction(signal, info, context);
+ }
+
static void AddActiveSampler(Sampler* sampler) {
ScopedLock lock(mutex_);
SamplerRegistry::AddActiveSampler(sampler);
@@ -1243,6 +1217,7 @@ class SignalSender : public Thread {
static SignalSender* instance_;
static bool signal_handler_installed_;
static struct sigaction old_signal_handler_;
+ static sigset_t old_signal_mask_;
private:
DISALLOW_COPY_AND_ASSIGN(SignalSender);
@@ -1253,6 +1228,72 @@ Mutex* SignalSender::mutex_ = NULL;
SignalSender* SignalSender::instance_ = NULL;
struct sigaction SignalSender::old_signal_handler_;
bool SignalSender::signal_handler_installed_ = false;
+sigset_t SignalSender::old_signal_mask_;
+
+
+static void ProfilerSignalHandlerInternal(
+ int signal, siginfo_t* info, void* context) {
+ USE(info);
+ if (signal != SIGPROF) return;
+ SignalSender::CallOldSignalHandler(signal, info, context);
+ Isolate* isolate = Isolate::UncheckedCurrent();
+ if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
+ // We require a fully initialized and entered isolate.
+ return;
+ }
+ if (v8::Locker::IsActive() &&
+ !isolate->thread_manager()->IsLockedByCurrentThread()) {
+ return;
+ }
+
+ Sampler* sampler = isolate->logger()->sampler();
+ if (sampler == NULL || !sampler->IsActive()) return;
+
+ TickSample sample_obj;
+ TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+ if (sample == NULL) sample = &sample_obj;
+
+ // Extracting the sample from the context is extremely machine dependent.
+ ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+ mcontext_t& mcontext = ucontext->uc_mcontext;
+ sample->state = isolate->current_vm_state();
+#if V8_HOST_ARCH_IA32
+ sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
+ sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
+ sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
+#elif V8_HOST_ARCH_X64
+ sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
+ sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
+ sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
+#elif V8_HOST_ARCH_ARM
+#if defined(__GLIBC__) && !defined(__UCLIBC__) && \
+ (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
+ // Old GLibc ARM versions used a gregs[] array to access the register
+ // values from mcontext_t.
+ sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
+ sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
+ sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
+#else
+ sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
+ sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
+ sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
+#endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
+ // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
+#elif V8_HOST_ARCH_MIPS
+ sample->pc = reinterpret_cast<Address>(mcontext.pc);
+ sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
+ sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
+#endif // V8_HOST_ARCH_*
+ sampler->SampleStack(sample);
+ sampler->Tick(sample);
+}
+
+
+static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
+ int curr_errno = errno;
+ ProfilerSignalHandlerInternal(signal, info, context);
+ errno = curr_errno;
+}
void OS::SetUp() {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698