* defs.h (wait_to_die_with_timeout): Declare.

* utils.c: #include "gdb_wait.h".
	(sigalrm_handler, wait_to_die_with_timeout): New functions.
	* ser-pipe.c: Don't #include "gdb_wait.h".
	(pipe_close): Give child a chance to die on its own after closing
	its stdin before SIGTERM'ing it.
This commit is contained in:
Doug Evans 2011-12-14 20:53:57 +00:00
parent afaabefa90
commit 0b6cb71e50
4 changed files with 106 additions and 5 deletions

View File

@ -1,3 +1,12 @@
2011-12-14 Doug Evans <dje@google.com>
* defs.h (wait_to_die_with_timeout): Declare.
* utils.c: #include "gdb_wait.h".
(sigalrm_handler, wait_to_die_with_timeout): New functions.
* ser-pipe.c: Don't #include "gdb_wait.h".
(pipe_close): Give child a chance to die on its own after closing
its stdin before SIGTERM'ing it.
2011-12-14 Joel Brobecker <brobecker@adacore.com>
Tom Tromey <tromey@redhat.com>

View File

@ -440,6 +440,10 @@ extern struct cleanup *make_bpstat_clear_actions_cleanup (void);
extern int producer_is_gcc_ge_4 (const char *producer);
#ifdef HAVE_WAITPID
extern pid_t wait_to_die_with_timeout (pid_t pid, int *status, int timeout);
#endif
/* Annotation stuff. */

View File

@ -31,7 +31,6 @@
#include <sys/time.h>
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_wait.h"
#include <signal.h>
@ -163,14 +162,30 @@ pipe_close (struct serial *scb)
if (state != NULL)
{
int status;
kill (state->pid, SIGTERM);
#ifdef HAVE_WAITPID
int wait_result, status;
/* Don't kill the task right away, give it a chance to shut down cleanly.
But don't wait forever though. */
#define PIPE_CLOSE_TIMEOUT 5
/* Assume the program will exit after SIGTERM. Might be
useful to print any remaining stderr output from
scb->error_fd while waiting. */
waitpid (state->pid, &status, 0);
#define SIGTERM_TIMEOUT INT_MAX
wait_result = -1;
#ifdef HAVE_WAITPID
wait_result = wait_to_die_with_timeout (state->pid, &status,
PIPE_CLOSE_TIMEOUT);
#endif
if (wait_result == -1)
{
kill (state->pid, SIGTERM);
#ifdef HAVE_WAITPID
wait_to_die_with_timeout (state->pid, &status, SIGTERM_TIMEOUT);
#endif
}
if (scb->error_fd != -1)
close (scb->error_fd);
scb->error_fd = -1;

View File

@ -24,6 +24,7 @@
#include "gdb_assert.h"
#include <ctype.h>
#include "gdb_string.h"
#include "gdb_wait.h"
#include "event-top.h"
#include "exceptions.h"
#include "gdbthread.h"
@ -3784,6 +3785,78 @@ producer_is_gcc_ge_4 (const char *producer)
return minor;
}
#ifdef HAVE_WAITPID
#ifdef SIGALRM
/* SIGALRM handler for waitpid_with_timeout. */
static void
sigalrm_handler (int signo)
{
/* Nothing to do. */
}
#endif
/* Wrapper to wait for child PID to die with TIMEOUT.
TIMEOUT is the time to stop waiting in seconds.
If TIMEOUT is zero, pass WNOHANG to waitpid.
Returns PID if it was successfully waited for, otherwise -1.
Timeouts are currently implemented with alarm and SIGALRM.
If the host does not support them, this waits "forever".
It would be odd though for a host to have waitpid and not SIGALRM. */
pid_t
wait_to_die_with_timeout (pid_t pid, int *status, int timeout)
{
pid_t waitpid_result;
gdb_assert (pid > 0);
gdb_assert (timeout >= 0);
if (timeout > 0)
{
#ifdef SIGALRM
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
struct sigaction sa, old_sa;
sa.sa_handler = sigalrm_handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sigaction (SIGALRM, &sa, &old_sa);
#else
void (*ofunc) ();
ofunc = (void (*)()) signal (SIGALRM, sigalrm_handler);
#endif
alarm (timeout);
#endif
waitpid_result = waitpid (pid, status, 0);
#ifdef SIGALRM
alarm (0);
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
sigaction (SIGALRM, &old_sa, NULL);
#else
signal (SIGALRM, ofunc);
#endif
#endif
}
else
waitpid_result = waitpid (pid, status, WNOHANG);
if (waitpid_result == pid)
return pid;
else
return -1;
}
#endif /* HAVE_WAITPID */
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_utils;