* defs.h (wait_to_die_with_timeout): Declare.
authorDoug Evans <dje@google.com>
Wed, 14 Dec 2011 20:53:57 +0000 (20:53 +0000)
committerDoug Evans <dje@google.com>
Wed, 14 Dec 2011 20:53:57 +0000 (20:53 +0000)
* 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.

gdb/ChangeLog
gdb/defs.h
gdb/ser-pipe.c
gdb/utils.c

index 0cce947..f9d4391 100644 (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>
 
index 040d9c9..7f8a330 100644 (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
+
 \f
 /* Annotation stuff.  */
 
index 9bf0d04..7f71987 100644 (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;
index cc93915..16405d1 100644 (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;