Use real time signal for threads instead of SIGURG.

This guarantees that any application is not also using this signal
for some other purpose.

Change-Id: I7c9bbb0ec8bb4e13322ecda951bcd43c6bf6ee1a
This commit is contained in:
Christopher Ferris 2014-04-29 09:35:30 -07:00
parent f3661cc2f1
commit aa63d9f980
3 changed files with 23 additions and 5 deletions

View file

@ -136,7 +136,7 @@ void BacktraceThread::FinishUnwind() {
bool BacktraceThread::TriggerUnwindOnThread(ThreadEntry* entry) {
entry->state = STATE_WAITING;
if (tgkill(Pid(), Tid(), SIGURG) != 0) {
if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
BACK_LOGW("tgkill failed %s", strerror(errno));
return false;
}
@ -196,9 +196,9 @@ bool BacktraceThread::Unwind(size_t num_ignore_frames) {
act.sa_sigaction = SignalHandler;
act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&act.sa_mask);
if (sigaction(SIGURG, &act, &oldact) == 0) {
if (sigaction(THREAD_SIGNAL, &act, &oldact) == 0) {
retval = TriggerUnwindOnThread(entry);
sigaction(SIGURG, &oldact, NULL);
sigaction(THREAD_SIGNAL, &oldact, NULL);
} else {
BACK_LOGW("sigaction failed %s", strerror(errno));
}

View file

@ -18,6 +18,7 @@
#define _LIBBACKTRACE_BACKTRACE_THREAD_H
#include <inttypes.h>
#include <signal.h>
#include <sys/types.h>
#include "BacktraceImpl.h"
@ -29,6 +30,14 @@ enum state_e {
STATE_CANCEL,
};
// The signal used to cause a thread to dump the stack.
#if defined(__GLIBC__)
// GLIBC reserves __SIGRTMIN signals, so use SIGRTMIN to avoid errors.
#define THREAD_SIGNAL SIGRTMIN
#else
#define THREAD_SIGNAL (__SIGRTMIN+1)
#endif
class BacktraceThreadInterface;
struct ThreadEntry {

View file

@ -33,6 +33,9 @@
#include <backtrace/BacktraceMap.h>
#include <UniquePtr.h>
// For the THREAD_SIGNAL definition.
#include "BacktraceThread.h"
#include <cutils/atomic.h>
#include <gtest/gtest.h>
@ -460,9 +463,15 @@ TEST(libbacktrace, thread_level_trace) {
// Wait up to 2 seconds for the tid to be set.
ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2));
// Make sure that the thread signal used is not visible when compiled for
// the target.
#if !defined(__GLIBC__)
ASSERT_LT(THREAD_SIGNAL, SIGRTMIN);
#endif
// Save the current signal action and make sure it is restored afterwards.
struct sigaction cur_action;
ASSERT_TRUE(sigaction(SIGURG, NULL, &cur_action) == 0);
ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &cur_action) == 0);
UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
ASSERT_TRUE(backtrace.get() != NULL);
@ -475,7 +484,7 @@ TEST(libbacktrace, thread_level_trace) {
// Verify that the old action was restored.
struct sigaction new_action;
ASSERT_TRUE(sigaction(SIGURG, NULL, &new_action) == 0);
ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &new_action) == 0);
EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction);
EXPECT_EQ(cur_action.sa_flags, new_action.sa_flags);
}