* lin-lwp.c (normal_mask, blocked_mask): New variables.
(lin_lwp_wait): Block SIGCHLD here if it isn't already blocked. (lin_lwp_mourn_inferior): Restore the origional signal mask, and reset the mask of blocked signals. (_initialize_lin_lwp): Don't block SIGCHLD here, but do initialize suspend_mask and blocked_mask. This makes us pass gdb.base/sigall.exp for Linux/x86 now. (lin_thread_get_thread_signals): Treat the LinuxThreads "cancel" signal similarly to SIGCHLD in the generic code. Avoids GDB being terminated by a Real-time signal.
This commit is contained in:
parent
7318608963
commit
3f07c44bc9
2 changed files with 75 additions and 14 deletions
|
@ -1,3 +1,16 @@
|
|||
2000-09-06 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* lin-lwp.c (normal_mask, blocked_mask): New variables.
|
||||
(lin_lwp_wait): Block SIGCHLD here if it isn't already blocked.
|
||||
(lin_lwp_mourn_inferior): Restore the origional signal mask, and
|
||||
reset the mask of blocked signals.
|
||||
(_initialize_lin_lwp): Don't block SIGCHLD here, but do initialize
|
||||
suspend_mask and blocked_mask. This makes us pass
|
||||
gdb.base/sigall.exp for Linux/x86 now.
|
||||
(lin_thread_get_thread_signals): Treat the LinuxThreads "cancel"
|
||||
signal similarly to SIGCHLD in the generic code. Avoids GDB being
|
||||
terminated by a Real-time signal.
|
||||
|
||||
2000-09-08 Kevin Buettner <kevinb@redhat.com>
|
||||
|
||||
* infptrace.c, infttrace.c (child_xfer_memory): Protoize.
|
||||
|
|
|
@ -55,9 +55,11 @@ extern const char *strsignal (int sig);
|
|||
code:
|
||||
|
||||
- In general one should specify the __WCLONE flag to waitpid in
|
||||
order to make it report events for any of the cloned processes.
|
||||
However, if a cloned process has exited the exit status is only
|
||||
reported if the __WCLONE flag is absent.
|
||||
order to make it report events for any of the cloned processes
|
||||
(and leave it out for the initial process). However, if a cloned
|
||||
process has exited the exit status is only reported if the
|
||||
__WCLONE flag is absent. Linux 2.4 has a __WALL flag, but we
|
||||
cannot use it since GDB must work on older systems too.
|
||||
|
||||
- When a traced, cloned process exits and is waited for by the
|
||||
debugger, the kernel reassigns it to the origional parent and
|
||||
|
@ -126,9 +128,26 @@ static struct target_ops lin_lwp_ops;
|
|||
/* The standard child operations. */
|
||||
extern struct target_ops child_ops;
|
||||
|
||||
/* Since we cannot wait (in lin_lwp_wait) for the initial process and
|
||||
any cloned processes with a single call to waitpid, we have to use
|
||||
use the WNOHANG flag and call waitpid in a loop. To optimize
|
||||
things a bit we use `sigsuspend' to wake us up when a process has
|
||||
something to report (it will send us a SIGCHLD if it has). To make
|
||||
this work we have to juggle with the signal mask. We save the
|
||||
origional signal mask such that we can restore it before creating a
|
||||
new process in order to avoid blocking certain signals in the
|
||||
inferior. We then block SIGCHLD during the waitpid/sigsuspend
|
||||
loop. */
|
||||
|
||||
/* Origional signal mask. */
|
||||
static sigset_t normal_mask;
|
||||
|
||||
/* Signal mask for use with sigsuspend in lin_lwp_wait, initialized in
|
||||
_initialize_lin_lwp. */
|
||||
static sigset_t suspend_mask;
|
||||
|
||||
/* Signals to block to make that sigsuspend work. */
|
||||
static sigset_t blocked_mask;
|
||||
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
|
@ -479,7 +498,7 @@ stop_wait_callback (struct lwp_info *lp, void *data)
|
|||
is_cloned (lp->pid) ? __WCLONE : 0);
|
||||
if (pid == -1 && errno == ECHILD)
|
||||
/* OK, the proccess has disappeared. We'll catch the actual
|
||||
exit event in lin_lwp_wait. */
|
||||
exit event in lin_lwp_wait. */
|
||||
return 0;
|
||||
|
||||
gdb_assert (pid == GET_LWP (lp->pid));
|
||||
|
@ -575,6 +594,13 @@ lin_lwp_wait (int pid, struct target_waitstatus *ourstatus)
|
|||
int options = 0;
|
||||
int status = 0;
|
||||
|
||||
/* Make sure SIGCHLD is blocked. */
|
||||
if (! sigismember (&blocked_mask, SIGCHLD))
|
||||
{
|
||||
sigaddset (&blocked_mask, SIGCHLD);
|
||||
sigprocmask (SIG_BLOCK, &blocked_mask, NULL);
|
||||
}
|
||||
|
||||
retry:
|
||||
|
||||
/* First check if there is a LWP with a wait status pending. */
|
||||
|
@ -659,7 +685,8 @@ lin_lwp_wait (int pid, struct target_waitstatus *ourstatus)
|
|||
lp = add_lwp (BUILD_LWP (lwpid, inferior_pid));
|
||||
if (threaded)
|
||||
{
|
||||
gdb_assert (WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP);
|
||||
gdb_assert (WIFSTOPPED (status)
|
||||
&& WSTOPSIG (status) == SIGSTOP);
|
||||
lp->signalled = 1;
|
||||
|
||||
if (! in_thread_list (inferior_pid))
|
||||
|
@ -863,6 +890,10 @@ lin_lwp_mourn_inferior (void)
|
|||
|
||||
trap_pid = 0;
|
||||
|
||||
/* Restore the origional signal mask. */
|
||||
sigprocmask (SIG_SETMASK, &normal_mask, NULL);
|
||||
sigemptyset (&blocked_mask);
|
||||
|
||||
#if 0
|
||||
target_beneath = find_target_beneath (&lin_lwp_ops);
|
||||
#else
|
||||
|
@ -978,7 +1009,6 @@ void
|
|||
_initialize_lin_lwp (void)
|
||||
{
|
||||
struct sigaction action;
|
||||
sigset_t mask;
|
||||
|
||||
extern void thread_db_init (struct target_ops *);
|
||||
|
||||
|
@ -986,18 +1016,19 @@ _initialize_lin_lwp (void)
|
|||
add_target (&lin_lwp_ops);
|
||||
thread_db_init (&lin_lwp_ops);
|
||||
|
||||
/* Save the origional signal mask. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &normal_mask);
|
||||
|
||||
action.sa_handler = sigchld_handler;
|
||||
sigemptyset (&action.sa_mask);
|
||||
action.sa_flags = 0;
|
||||
sigaction (SIGCHLD, &action, NULL);
|
||||
|
||||
/* We block SIGCHLD throughout this code ... */
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, SIGCHLD);
|
||||
sigprocmask (SIG_BLOCK, &mask, &suspend_mask);
|
||||
|
||||
/* ... except during a sigsuspend. */
|
||||
/* Make sure we don't block SIGCHLD during a sigsuspend. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &suspend_mask);
|
||||
sigdelset (&suspend_mask, SIGCHLD);
|
||||
|
||||
sigemptyset (&blocked_mask);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1030,8 +1061,8 @@ get_signo (const char *name)
|
|||
void
|
||||
lin_thread_get_thread_signals (sigset_t *set)
|
||||
{
|
||||
int restart;
|
||||
int cancel;
|
||||
struct sigaction action;
|
||||
int restart, cancel;
|
||||
|
||||
sigemptyset (set);
|
||||
|
||||
|
@ -1045,4 +1076,21 @@ lin_thread_get_thread_signals (sigset_t *set)
|
|||
|
||||
sigaddset (set, restart);
|
||||
sigaddset (set, cancel);
|
||||
|
||||
/* The LinuxThreads library makes terminating threads send a special
|
||||
"cancel" signal instead of SIGCHLD. Make sure we catch those (to
|
||||
prevent them from terminating GDB itself, which is likely to be
|
||||
their default action) and treat them the same way as SIGCHLD. */
|
||||
|
||||
action.sa_handler = sigchld_handler;
|
||||
sigemptyset (&action.sa_mask);
|
||||
action.sa_flags = 0;
|
||||
sigaction (cancel, &action, NULL);
|
||||
|
||||
/* We block the "cancel" signal throughout this code ... */
|
||||
sigaddset (&blocked_mask, cancel);
|
||||
sigprocmask (SIG_BLOCK, &blocked_mask, NULL);
|
||||
|
||||
/* ... except during a sigsuspend. */
|
||||
sigdelset (&suspend_mask, cancel);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue