* Check the thread debug signal ignore masks before notifying the debugger
of a signal. * Added sigaction_etc(). It's just a sigaction() for which the thread in question can be specified. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11704 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -21,6 +21,9 @@ extern "C" {
|
|||||||
extern int handle_signals(struct thread *t, cpu_status *state);
|
extern int handle_signals(struct thread *t, cpu_status *state);
|
||||||
extern bool is_kill_signal_pending(void);
|
extern bool is_kill_signal_pending(void);
|
||||||
|
|
||||||
|
extern int sigaction_etc(thread_id threadID, int signal,
|
||||||
|
const struct sigaction *act, struct sigaction *oact);
|
||||||
|
|
||||||
extern int _user_send_signal(pid_t tid, uint sig);
|
extern int _user_send_signal(pid_t tid, uint sig);
|
||||||
extern int _user_sigprocmask(int how, const sigset_t *set, sigset_t *oldSet);
|
extern int _user_sigprocmask(int how, const sigset_t *set, sigset_t *oldSet);
|
||||||
extern int _user_sigaction(int sig, const struct sigaction *action, struct sigaction *oldAction);
|
extern int _user_sigaction(int sig, const struct sigaction *action, struct sigaction *oldAction);
|
||||||
|
|||||||
+65
-21
@@ -41,10 +41,23 @@ const char * const sigstr[NSIG] = {
|
|||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
notify_debugger(int signal, struct sigaction *handler, bool deadly,
|
notify_debugger(struct thread *thread, int signal, struct sigaction *handler,
|
||||||
cpu_status *state)
|
bool deadly, cpu_status *state)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
|
uint64 signalMask = SIGNAL_TO_MASK(signal);
|
||||||
|
|
||||||
|
// first check the ignore signal masks the debugger specified for the thread
|
||||||
|
|
||||||
|
if (thread->debug_info.ignore_signals_once & signalMask) {
|
||||||
|
thread->debug_info.ignore_signals_once &= ~signalMask;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thread->debug_info.ignore_signals & signalMask)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// deliver the event
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(*state);
|
restore_interrupts(*state);
|
||||||
@@ -108,7 +121,7 @@ handle_signals(struct thread *thread, cpu_status *state)
|
|||||||
|
|
||||||
// notify the debugger
|
// notify the debugger
|
||||||
if (debugSignal)
|
if (debugSignal)
|
||||||
notify_debugger(sig, handler, false, state);
|
notify_debugger(thread, sig, handler, false, state);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (handler->sa_handler == SIG_DFL) {
|
if (handler->sa_handler == SIG_DFL) {
|
||||||
@@ -121,15 +134,18 @@ handle_signals(struct thread *thread, cpu_status *state)
|
|||||||
case SIGTTOU:
|
case SIGTTOU:
|
||||||
case SIGCONT:
|
case SIGCONT:
|
||||||
// notify the debugger
|
// notify the debugger
|
||||||
if (debugSignal)
|
if (debugSignal) {
|
||||||
notify_debugger(sig, handler, false, state);
|
notify_debugger(thread, sig, handler, false, state);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case SIGSTOP:
|
case SIGSTOP:
|
||||||
// notify the debugger
|
// notify the debugger
|
||||||
if (debugSignal) {
|
if (debugSignal) {
|
||||||
if (!notify_debugger(sig, handler, false, state))
|
if (!notify_debugger(thread, sig, handler, false,
|
||||||
|
state)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->next_state = B_THREAD_SUSPENDED;
|
thread->next_state = B_THREAD_SUSPENDED;
|
||||||
@@ -152,8 +168,10 @@ handle_signals(struct thread *thread, cpu_status *state)
|
|||||||
// notify the debugger
|
// notify the debugger
|
||||||
if (debugSignal && sig != SIGKILL
|
if (debugSignal && sig != SIGKILL
|
||||||
&& sig != SIGKILLTHR) {
|
&& sig != SIGKILLTHR) {
|
||||||
if (!notify_debugger(sig, handler, true, state))
|
if (!notify_debugger(thread, sig, handler, true,
|
||||||
|
state)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
@@ -173,7 +191,7 @@ handle_signals(struct thread *thread, cpu_status *state)
|
|||||||
|
|
||||||
// notify the debugger
|
// notify the debugger
|
||||||
if (debugSignal) {
|
if (debugSignal) {
|
||||||
if (!notify_debugger(sig, handler, false, state))
|
if (!notify_debugger(thread, sig, handler, false, state))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,11 +431,18 @@ sigprocmask(int how, const sigset_t *set, sigset_t *oldSet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Similar to sigaction(), just for a specified thread.
|
||||||
|
*
|
||||||
|
* A \a threadID is < 0 specifies the current thread.
|
||||||
|
*
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
sigaction(int signal, const struct sigaction *act, struct sigaction *oact)
|
sigaction_etc(thread_id threadID, int signal, const struct sigaction *act,
|
||||||
|
struct sigaction *oact)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
cpu_status state;
|
cpu_status state;
|
||||||
|
status_t error = B_OK;
|
||||||
|
|
||||||
if (signal < 1 || signal > MAX_SIGNO
|
if (signal < 1 || signal > MAX_SIGNO
|
||||||
|| signal == SIGKILL || signal == SIGKILLTHR || signal == SIGSTOP)
|
|| signal == SIGKILL || signal == SIGKILLTHR || signal == SIGSTOP)
|
||||||
@@ -426,25 +451,44 @@ sigaction(int signal, const struct sigaction *act, struct sigaction *oact)
|
|||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
thread = thread_get_current_thread();
|
thread = (threadID < 0
|
||||||
|
? thread_get_current_thread()
|
||||||
|
: thread_get_thread_struct_locked(threadID));
|
||||||
|
|
||||||
if (oact)
|
if (thread) {
|
||||||
memcpy(oact, &thread->sig_action[signal - 1], sizeof(struct sigaction));
|
if (oact) {
|
||||||
if (act)
|
memcpy(oact, &thread->sig_action[signal - 1],
|
||||||
memcpy(&thread->sig_action[signal - 1], act, sizeof(struct sigaction));
|
sizeof(struct sigaction));
|
||||||
|
}
|
||||||
|
|
||||||
if (act && act->sa_handler == SIG_IGN)
|
if (act) {
|
||||||
thread->sig_pending &= ~SIGNAL_TO_MASK(signal);
|
memcpy(&thread->sig_action[signal - 1], act,
|
||||||
else if (act && act->sa_handler == SIG_DFL) {
|
sizeof(struct sigaction));
|
||||||
if (signal == SIGCONT || signal == SIGCHLD || signal == SIGWINCH)
|
}
|
||||||
|
|
||||||
|
if (act && act->sa_handler == SIG_IGN)
|
||||||
thread->sig_pending &= ~SIGNAL_TO_MASK(signal);
|
thread->sig_pending &= ~SIGNAL_TO_MASK(signal);
|
||||||
} /*else
|
else if (act && act->sa_handler == SIG_DFL) {
|
||||||
dprintf("### custom signal handler set\n");*/
|
if (signal == SIGCONT || signal == SIGCHLD
|
||||||
|
|| signal == SIGWINCH) {
|
||||||
|
thread->sig_pending &= ~SIGNAL_TO_MASK(signal);
|
||||||
|
}
|
||||||
|
} /*else
|
||||||
|
dprintf("### custom signal handler set\n");*/
|
||||||
|
} else
|
||||||
|
error = B_BAD_THREAD_ID;
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
return 0;
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
sigaction(int signal, const struct sigaction *act, struct sigaction *oact)
|
||||||
|
{
|
||||||
|
return sigaction_etc(-1, signal, act, oact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user