gdb/
2008-06-28 Pedro Alves <pedro@codesourcery.com> * linux-nat.c (enum sigchld_state): New. (linux_nat_async_events_state): Renamed from linux_nat_async_events_enabled. (linux_nat_event_pipe_push, my_waitpid): Adjust. (sigchld_default_action): New. (lin_lwp_attach_lwp): Adjust. Call linux_nat_async_events unconditionally. (linux_nat_create_inferior): Set events state to sigchld_default state. (linux_nat_resume): Adjust. (linux_nat_wait): Call linux_nat_async_events unconditionally. (sigchld_handler): Adjust. (linux_nat_async_mask): Don't set SIGCHLD actions here. (get_pending_events): Adjust. (linux_nat_async_events): Rewrite to handle enum sigchld_state instead of a boolean. (linux_nat_async): Adjust. (_initialize_linux_nat): Capture default SIGCHLD action into sigchld_default_action. gdb/testsuite/ 2008-06-28 Pedro Alves <pedro@codesourcery.com> * gdb.base/sigchld.c, gdb.base/sigchld.exp: New test.
This commit is contained in:
parent
0f8d4a2f6e
commit
84e46146f7
5 changed files with 209 additions and 57 deletions
|
@ -1,3 +1,25 @@
|
||||||
|
2008-06-28 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
|
* linux-nat.c (enum sigchld_state): New.
|
||||||
|
(linux_nat_async_events_state): Renamed from
|
||||||
|
linux_nat_async_events_enabled.
|
||||||
|
(linux_nat_event_pipe_push, my_waitpid): Adjust.
|
||||||
|
(sigchld_default_action): New.
|
||||||
|
(lin_lwp_attach_lwp): Adjust. Call linux_nat_async_events
|
||||||
|
unconditionally.
|
||||||
|
(linux_nat_create_inferior): Set events state to sigchld_default
|
||||||
|
state.
|
||||||
|
(linux_nat_resume): Adjust.
|
||||||
|
(linux_nat_wait): Call linux_nat_async_events unconditionally.
|
||||||
|
(sigchld_handler): Adjust.
|
||||||
|
(linux_nat_async_mask): Don't set SIGCHLD actions here.
|
||||||
|
(get_pending_events): Adjust.
|
||||||
|
(linux_nat_async_events): Rewrite to handle enum sigchld_state
|
||||||
|
instead of a boolean.
|
||||||
|
(linux_nat_async): Adjust.
|
||||||
|
(_initialize_linux_nat): Capture default SIGCHLD action into
|
||||||
|
sigchld_default_action.
|
||||||
|
|
||||||
2008-06-28 Vladimir Prus <vladimir@codesourcery.com>
|
2008-06-28 Vladimir Prus <vladimir@codesourcery.com>
|
||||||
|
|
||||||
* breakpoint.c (moribund_locations): New.
|
* breakpoint.c (moribund_locations): New.
|
||||||
|
|
146
gdb/linux-nat.c
146
gdb/linux-nat.c
|
@ -256,11 +256,24 @@ static int linux_nat_event_pipe[2] = { -1, -1 };
|
||||||
/* Number of queued events in the pipe. */
|
/* Number of queued events in the pipe. */
|
||||||
static volatile int linux_nat_num_queued_events;
|
static volatile int linux_nat_num_queued_events;
|
||||||
|
|
||||||
/* If async mode is on, true if we're listening for events; false if
|
/* The possible SIGCHLD handling states. */
|
||||||
target events are blocked. */
|
|
||||||
static int linux_nat_async_events_enabled;
|
|
||||||
|
|
||||||
static int linux_nat_async_events (int enable);
|
enum sigchld_state
|
||||||
|
{
|
||||||
|
/* SIGCHLD disabled, with action set to sigchld_handler, for the
|
||||||
|
sigsuspend in linux_nat_wait. */
|
||||||
|
sigchld_sync,
|
||||||
|
/* SIGCHLD enabled, with action set to async_sigchld_handler. */
|
||||||
|
sigchld_async,
|
||||||
|
/* Set SIGCHLD to default action. Used while creating an
|
||||||
|
inferior. */
|
||||||
|
sigchld_default
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The current SIGCHLD handling state. */
|
||||||
|
static enum sigchld_state linux_nat_async_events_state;
|
||||||
|
|
||||||
|
static enum sigchld_state linux_nat_async_events (enum sigchld_state enable);
|
||||||
static void pipe_to_local_event_queue (void);
|
static void pipe_to_local_event_queue (void);
|
||||||
static void local_event_queue_to_pipe (void);
|
static void local_event_queue_to_pipe (void);
|
||||||
static void linux_nat_event_pipe_push (int pid, int status, int options);
|
static void linux_nat_event_pipe_push (int pid, int status, int options);
|
||||||
|
@ -294,8 +307,8 @@ queued_waitpid (int pid, int *status, int flags)
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat_async)
|
||||||
fprintf_unfiltered (gdb_stdlog,
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
"\
|
"\
|
||||||
QWPID: linux_nat_async_events_enabled(%d), linux_nat_num_queued_events(%d)\n",
|
QWPID: linux_nat_async_events_state(%d), linux_nat_num_queued_events(%d)\n",
|
||||||
linux_nat_async_events_enabled,
|
linux_nat_async_events_state,
|
||||||
linux_nat_num_queued_events);
|
linux_nat_num_queued_events);
|
||||||
|
|
||||||
if (flags & __WALL)
|
if (flags & __WALL)
|
||||||
|
@ -441,7 +454,7 @@ my_waitpid (int pid, int *status, int flags)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* There should be no concurrent calls to waitpid. */
|
/* There should be no concurrent calls to waitpid. */
|
||||||
gdb_assert (!linux_nat_async_events_enabled);
|
gdb_assert (linux_nat_async_events_state == sigchld_sync);
|
||||||
|
|
||||||
ret = queued_waitpid (pid, status, flags);
|
ret = queued_waitpid (pid, status, flags);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
|
@ -862,6 +875,9 @@ struct sigaction sync_sigchld_action;
|
||||||
|
|
||||||
/* SIGCHLD action for asynchronous mode. */
|
/* SIGCHLD action for asynchronous mode. */
|
||||||
static struct sigaction async_sigchld_action;
|
static struct sigaction async_sigchld_action;
|
||||||
|
|
||||||
|
/* SIGCHLD default action, to pass to new inferiors. */
|
||||||
|
static struct sigaction sigchld_default_action;
|
||||||
|
|
||||||
|
|
||||||
/* Prototypes for local functions. */
|
/* Prototypes for local functions. */
|
||||||
|
@ -1185,12 +1201,11 @@ int
|
||||||
lin_lwp_attach_lwp (ptid_t ptid)
|
lin_lwp_attach_lwp (ptid_t ptid)
|
||||||
{
|
{
|
||||||
struct lwp_info *lp;
|
struct lwp_info *lp;
|
||||||
int async_events_were_enabled = 0;
|
enum sigchld_state async_events_original_state;
|
||||||
|
|
||||||
gdb_assert (is_lwp (ptid));
|
gdb_assert (is_lwp (ptid));
|
||||||
|
|
||||||
if (target_can_async_p ())
|
async_events_original_state = linux_nat_async_events (sigchld_sync);
|
||||||
async_events_were_enabled = linux_nat_async_events (0);
|
|
||||||
|
|
||||||
lp = find_lwp_pid (ptid);
|
lp = find_lwp_pid (ptid);
|
||||||
|
|
||||||
|
@ -1255,9 +1270,7 @@ lin_lwp_attach_lwp (ptid_t ptid)
|
||||||
lp->stopped = 1;
|
lp->stopped = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (async_events_were_enabled)
|
linux_nat_async_events (async_events_original_state);
|
||||||
linux_nat_async_events (1);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,6 +1284,8 @@ linux_nat_create_inferior (char *exec_file, char *allargs, char **env,
|
||||||
we have to mask the async mode. */
|
we have to mask the async mode. */
|
||||||
|
|
||||||
if (target_can_async_p ())
|
if (target_can_async_p ())
|
||||||
|
/* Mask async mode. Creating a child requires a loop calling
|
||||||
|
wait_for_inferior currently. */
|
||||||
saved_async = linux_nat_async_mask (0);
|
saved_async = linux_nat_async_mask (0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1281,6 +1296,12 @@ linux_nat_create_inferior (char *exec_file, char *allargs, char **env,
|
||||||
sigdelset (&suspend_mask, SIGCHLD);
|
sigdelset (&suspend_mask, SIGCHLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set SIGCHLD to the default action, until after execing the child,
|
||||||
|
since the inferior inherits the superior's signal mask. It will
|
||||||
|
be blocked again in linux_nat_wait, which is only reached after
|
||||||
|
the inferior execing. */
|
||||||
|
linux_nat_async_events (sigchld_default);
|
||||||
|
|
||||||
linux_ops->to_create_inferior (exec_file, allargs, env, from_tty);
|
linux_ops->to_create_inferior (exec_file, allargs, env, from_tty);
|
||||||
|
|
||||||
if (saved_async)
|
if (saved_async)
|
||||||
|
@ -1512,7 +1533,7 @@ linux_nat_resume (ptid_t ptid, int step, enum target_signal signo)
|
||||||
|
|
||||||
if (target_can_async_p ())
|
if (target_can_async_p ())
|
||||||
/* Block events while we're here. */
|
/* Block events while we're here. */
|
||||||
linux_nat_async_events (0);
|
linux_nat_async_events (sigchld_sync);
|
||||||
|
|
||||||
/* A specific PTID means `step only this process id'. */
|
/* A specific PTID means `step only this process id'. */
|
||||||
resume_all = (PIDGET (ptid) == -1);
|
resume_all = (PIDGET (ptid) == -1);
|
||||||
|
@ -2574,9 +2595,8 @@ linux_nat_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||||
|
|
||||||
sigemptyset (&flush_mask);
|
sigemptyset (&flush_mask);
|
||||||
|
|
||||||
if (target_can_async_p ())
|
|
||||||
/* Block events while we're here. */
|
/* Block events while we're here. */
|
||||||
target_async (NULL, 0);
|
linux_nat_async_events (sigchld_sync);
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
|
|
||||||
|
@ -3035,7 +3055,7 @@ static void
|
||||||
sigchld_handler (int signo)
|
sigchld_handler (int signo)
|
||||||
{
|
{
|
||||||
if (linux_nat_async_enabled
|
if (linux_nat_async_enabled
|
||||||
&& linux_nat_async_events_enabled
|
&& linux_nat_async_events_state != sigchld_sync
|
||||||
&& signo == SIGCHLD)
|
&& signo == SIGCHLD)
|
||||||
/* It is *always* a bug to hit this. */
|
/* It is *always* a bug to hit this. */
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
|
@ -3894,15 +3914,9 @@ linux_nat_async_mask (int mask)
|
||||||
{
|
{
|
||||||
linux_nat_async (NULL, 0);
|
linux_nat_async (NULL, 0);
|
||||||
linux_nat_async_mask_value = mask;
|
linux_nat_async_mask_value = mask;
|
||||||
/* We're in sync mode. Make sure SIGCHLD isn't handled by
|
|
||||||
async_sigchld_handler when we come out of sigsuspend in
|
|
||||||
linux_nat_wait. */
|
|
||||||
sigaction (SIGCHLD, &sync_sigchld_action, NULL);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Restore the async handler. */
|
|
||||||
sigaction (SIGCHLD, &async_sigchld_action, NULL);
|
|
||||||
linux_nat_async_mask_value = mask;
|
linux_nat_async_mask_value = mask;
|
||||||
linux_nat_async (inferior_event_handler, 0);
|
linux_nat_async (inferior_event_handler, 0);
|
||||||
}
|
}
|
||||||
|
@ -3960,7 +3974,8 @@ get_pending_events (void)
|
||||||
{
|
{
|
||||||
int status, options, pid;
|
int status, options, pid;
|
||||||
|
|
||||||
if (!linux_nat_async_enabled || !linux_nat_async_events_enabled)
|
if (!linux_nat_async_enabled
|
||||||
|
|| linux_nat_async_events_state != sigchld_async)
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
"get_pending_events called with async masked");
|
"get_pending_events called with async masked");
|
||||||
|
|
||||||
|
@ -4014,45 +4029,76 @@ async_sigchld_handler (int signo)
|
||||||
get_pending_events ();
|
get_pending_events ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable or disable async SIGCHLD handling. */
|
/* Set SIGCHLD handling state to STATE. Returns previous state. */
|
||||||
|
|
||||||
static int
|
static enum sigchld_state
|
||||||
linux_nat_async_events (int enable)
|
linux_nat_async_events (enum sigchld_state state)
|
||||||
{
|
{
|
||||||
int current_state = linux_nat_async_events_enabled;
|
enum sigchld_state current_state = linux_nat_async_events_state;
|
||||||
|
|
||||||
if (debug_linux_nat_async)
|
if (debug_linux_nat_async)
|
||||||
fprintf_unfiltered (gdb_stdlog,
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
"LNAE: enable(%d): linux_nat_async_events_enabled(%d), "
|
"LNAE: state(%d): linux_nat_async_events_state(%d), "
|
||||||
"linux_nat_num_queued_events(%d)\n",
|
"linux_nat_num_queued_events(%d)\n",
|
||||||
enable, linux_nat_async_events_enabled,
|
state, linux_nat_async_events_state,
|
||||||
linux_nat_num_queued_events);
|
linux_nat_num_queued_events);
|
||||||
|
|
||||||
if (current_state != enable)
|
if (current_state != state)
|
||||||
{
|
{
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
sigemptyset (&mask);
|
sigemptyset (&mask);
|
||||||
sigaddset (&mask, SIGCHLD);
|
sigaddset (&mask, SIGCHLD);
|
||||||
if (enable)
|
|
||||||
{
|
|
||||||
/* Unblock target events. */
|
|
||||||
linux_nat_async_events_enabled = 1;
|
|
||||||
|
|
||||||
local_event_queue_to_pipe ();
|
/* Always block before changing state. */
|
||||||
/* While in masked async, we may have not collected all the
|
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||||
pending events. Get them out now. */
|
|
||||||
get_pending_events ();
|
/* Set new state. */
|
||||||
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
linux_nat_async_events_state = state;
|
||||||
}
|
|
||||||
else
|
switch (state)
|
||||||
|
{
|
||||||
|
case sigchld_sync:
|
||||||
{
|
{
|
||||||
/* Block target events. */
|
/* Block target events. */
|
||||||
sigprocmask (SIG_BLOCK, &mask, NULL);
|
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||||
linux_nat_async_events_enabled = 0;
|
sigaction (SIGCHLD, &sync_sigchld_action, NULL);
|
||||||
/* Get events out of queue, and make them available to
|
/* Get events out of queue, and make them available to
|
||||||
queued_waitpid / my_waitpid. */
|
queued_waitpid / my_waitpid. */
|
||||||
pipe_to_local_event_queue ();
|
pipe_to_local_event_queue ();
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case sigchld_async:
|
||||||
|
{
|
||||||
|
/* Unblock target events for async mode. */
|
||||||
|
|
||||||
|
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||||
|
|
||||||
|
/* Put events we already waited on, in the pipe first, so
|
||||||
|
events are FIFO. */
|
||||||
|
local_event_queue_to_pipe ();
|
||||||
|
/* While in masked async, we may have not collected all
|
||||||
|
the pending events. Get them out now. */
|
||||||
|
get_pending_events ();
|
||||||
|
|
||||||
|
/* Let'em come. */
|
||||||
|
sigaction (SIGCHLD, &async_sigchld_action, NULL);
|
||||||
|
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case sigchld_default:
|
||||||
|
{
|
||||||
|
/* SIGCHLD default mode. */
|
||||||
|
sigaction (SIGCHLD, &sigchld_default_action, NULL);
|
||||||
|
|
||||||
|
/* Get events out of queue, and make them available to
|
||||||
|
queued_waitpid / my_waitpid. */
|
||||||
|
pipe_to_local_event_queue ();
|
||||||
|
|
||||||
|
/* Unblock SIGCHLD. */
|
||||||
|
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_state;
|
return current_state;
|
||||||
|
@ -4143,14 +4189,14 @@ linux_nat_async (void (*callback) (enum inferior_event_type event_type,
|
||||||
add_file_handler (linux_nat_event_pipe[0],
|
add_file_handler (linux_nat_event_pipe[0],
|
||||||
linux_nat_async_file_handler, NULL);
|
linux_nat_async_file_handler, NULL);
|
||||||
|
|
||||||
linux_nat_async_events (1);
|
linux_nat_async_events (sigchld_async);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
async_client_callback = callback;
|
async_client_callback = callback;
|
||||||
async_client_context = context;
|
async_client_context = context;
|
||||||
|
|
||||||
linux_nat_async_events (0);
|
linux_nat_async_events (sigchld_sync);
|
||||||
delete_file_handler (linux_nat_event_pipe[0]);
|
delete_file_handler (linux_nat_event_pipe[0]);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -4166,21 +4212,15 @@ linux_nat_set_async_mode (int on)
|
||||||
if (on)
|
if (on)
|
||||||
{
|
{
|
||||||
gdb_assert (waitpid_queue == NULL);
|
gdb_assert (waitpid_queue == NULL);
|
||||||
sigaction (SIGCHLD, &async_sigchld_action, NULL);
|
|
||||||
|
|
||||||
if (pipe (linux_nat_event_pipe) == -1)
|
if (pipe (linux_nat_event_pipe) == -1)
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
"creating event pipe failed.");
|
"creating event pipe failed.");
|
||||||
|
|
||||||
fcntl (linux_nat_event_pipe[0], F_SETFL, O_NONBLOCK);
|
fcntl (linux_nat_event_pipe[0], F_SETFL, O_NONBLOCK);
|
||||||
fcntl (linux_nat_event_pipe[1], F_SETFL, O_NONBLOCK);
|
fcntl (linux_nat_event_pipe[1], F_SETFL, O_NONBLOCK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sigaction (SIGCHLD, &sync_sigchld_action, NULL);
|
|
||||||
|
|
||||||
drain_queued_events (-1);
|
drain_queued_events (-1);
|
||||||
|
|
||||||
linux_nat_num_queued_events = 0;
|
linux_nat_num_queued_events = 0;
|
||||||
close (linux_nat_event_pipe[0]);
|
close (linux_nat_event_pipe[0]);
|
||||||
close (linux_nat_event_pipe[1]);
|
close (linux_nat_event_pipe[1]);
|
||||||
|
@ -4297,6 +4337,10 @@ Tells gdb whether to control the GNU/Linux inferior in asynchronous mode."),
|
||||||
&maintenance_set_cmdlist,
|
&maintenance_set_cmdlist,
|
||||||
&maintenance_show_cmdlist);
|
&maintenance_show_cmdlist);
|
||||||
|
|
||||||
|
/* Get the default SIGCHLD action. Used while forking an inferior
|
||||||
|
(see linux_nat_create_inferior/linux_nat_async_events). */
|
||||||
|
sigaction (SIGCHLD, NULL, &sigchld_default_action);
|
||||||
|
|
||||||
/* Block SIGCHLD by default. Doing this early prevents it getting
|
/* Block SIGCHLD by default. Doing this early prevents it getting
|
||||||
unblocked if an exception is thrown due to an error while the
|
unblocked if an exception is thrown due to an error while the
|
||||||
inferior is starting (sigsetjmp/siglongjmp). */
|
inferior is starting (sigsetjmp/siglongjmp). */
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2008-06-28 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
|
* gdb.base/sigchld.c, gdb.base/sigchld.exp: New test.
|
||||||
|
|
||||||
2008-06-28 Vladimir Prus <vladimir@codesourcery.com>
|
2008-06-28 Vladimir Prus <vladimir@codesourcery.com>
|
||||||
|
|
||||||
* lib/mi-support.exp (mi_send_resuming_command_raw): Report pass.
|
* lib/mi-support.exp (mi_send_resuming_command_raw): Report pass.
|
||||||
|
|
37
gdb/testsuite/gdb.base/sigchld.c
Normal file
37
gdb/testsuite/gdb.base/sigchld.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Check that GDB isn't messing the SIGCHLD mask while creating an
|
||||||
|
inferior. */
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
sigset_t mask;
|
||||||
|
|
||||||
|
sigemptyset (&mask);
|
||||||
|
sigprocmask (SIG_BLOCK, NULL, &mask);
|
||||||
|
|
||||||
|
if (!sigismember (&mask, SIGCHLD))
|
||||||
|
return 0; /* good, not blocked */
|
||||||
|
else
|
||||||
|
return 1; /* bad, blocked */
|
||||||
|
}
|
45
gdb/testsuite/gdb.base/sigchld.exp
Normal file
45
gdb/testsuite/gdb.base/sigchld.exp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Copyright (C) 2008 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Check that GDB isn't messing the SIGCHLD mask while creating an
|
||||||
|
# inferior.
|
||||||
|
|
||||||
|
if [target_info exists gdb,nosignals] {
|
||||||
|
verbose "Skipping sigchld.exp because of nosignals."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
set testfile "sigchld"
|
||||||
|
set srcfile ${testfile}.c
|
||||||
|
set binfile ${objdir}/${subdir}/${testfile}
|
||||||
|
|
||||||
|
if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_exit
|
||||||
|
gdb_start
|
||||||
|
gdb_reinitialize_dir $srcdir/$subdir
|
||||||
|
gdb_load ${binfile}
|
||||||
|
|
||||||
|
runto_main
|
||||||
|
|
||||||
|
gdb_test "b [gdb_get_line_number "good, not blocked"]" \
|
||||||
|
".*Breakpoint .*sigchld.*" "set breakpoint at success exit"
|
||||||
|
|
||||||
|
gdb_test "b [gdb_get_line_number "bad, blocked"]" \
|
||||||
|
".*Breakpoint .*sigchld.*" "set breakpoint at failure exit"
|
||||||
|
|
||||||
|
gdb_test "continue" ".*good, not blocked.*" "SIGCHLD blocked in inferior"
|
Loading…
Add table
Add a link
Reference in a new issue