If the capture child process exits unexpectedly, give more information
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 27 Dec 2000 22:35:48 +0000 (22:35 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Wed, 27 Dec 2000 22:35:48 +0000 (22:35 +0000)
on it, such as the exit status if it exited "normally" but unexpectedly.

On UNIX systems, #define the various POSIX <sys/wait.h> macros (and the
non-POSIX WCOREDUMP()" macro) if they're not defined by <sys/wait.h> (or
if we don't have <sys/wait.h>), and use them to dissect the exit status.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@2788 f5534014-38df-0310-8fa8-9805f1628bb7

capture.c

index 9b0cd19372914db3bc4f0753b7059c3dbd2bb3ae..2cf6f25c616d1fe475e134ce8a19dc9451b53ffc 100644 (file)
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
 /* capture.c
  * Routines for packet capture windows
  *
- * $Id: capture.c,v 1.132 2000/11/15 05:41:41 guy Exp $
+ * $Id: capture.c,v 1.133 2000/12/27 22:35:48 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 #ifdef HAVE_SYS_WAIT_H
 # include <sys/wait.h>
 #endif
+
+#ifndef _WIN32
+/*
+ * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
+ * macros) on UNIX systems that don't have them.
+ */
+#ifndef WIFEXITED
+# define WIFEXITED(status)     (((status) & 0177) == 0)
+#endif
+#ifndef WIFSTOPPED
+# define WIFSTOPPED(status)    (((status) & 0177) == 0177)
+#endif
+#ifndef WIFSIGNALED
+# define WIFSIGNALED(status)   (!WIFSTOPPED(status) && !WIFEXITED(status))
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(status)   ((status) >> 8)
+#endif
+#ifndef WTERMSIG
+# define WTERMSIG(status)      ((status) & 0177)
+#endif
+#ifndef WCOREDUMP
+# define WCOREDUMP(status)     ((status) & 0200)
+#endif
+#ifndef WSTOPSIG
+# define WSTOPSIG(status)      ((status) >> 8)
+#endif
+#endif /* _WIN32 */
+
 #ifdef HAVE_IO_H
-#include <io.h>
+# include <io.h>
 #endif
 
 #include <gtk/gtk.h>
@@ -121,6 +150,10 @@ static int cap_timer_cb(gpointer); /* Win32 kludge to check for pipe input */
 #endif
 
 static void cap_file_input_cb(gpointer, gint, GdkInputCondition);
+static void wait_for_child(gboolean);
+#ifndef _WIN32
+static char *signame(int);
+#endif
 static void capture_delete_cb(GtkWidget *, GdkEvent *, gpointer);
 static void capture_stop_cb(GtkWidget *, gpointer);
 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
@@ -404,13 +437,12 @@ do_capture(char *capfile_name)
       if (i == 0) {
        /* EOF - the child process died.
           Close the read side of the sync pipe, remove the capture file,
-          and report the failure.
-          XXX - reap the child process and report the status in detail. */
+          and report the failure. */
        close(sync_pipe[READ]);
        unlink(cfile.save_file);
        g_free(cfile.save_file);
        cfile.save_file = NULL;
-       simple_dialog(ESD_TYPE_WARN, NULL, "Capture child process died");
+       wait_for_child(TRUE);
        return;
       }
       if (c == ';')
@@ -482,6 +514,7 @@ do_capture(char *capfile_name)
        } else if (i == 0) {
          simple_dialog(ESD_TYPE_WARN, NULL,
                  "Capture child process failed: EOF reading its error message.");
+         wait_for_child(FALSE);
        } else
          simple_dialog(ESD_TYPE_WARN, NULL, msg);
        g_free(msg);
@@ -583,12 +616,6 @@ cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
   int  to_read = 0;
   gboolean exit_loop = FALSE;
   int  err;
-  int  wstatus;
-  int  wsignal;
-  char *msg;
-  char *sigmsg;
-  char sigmsg_buf[6+1+3+1];
-  char *coredumped;
 
 #ifndef _WIN32
   /* avoid reentrancy problems and stack overflow */
@@ -598,112 +625,8 @@ cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
   if ((nread = read(sync_pipe[READ], buffer, 256)) <= 0) {
     /* The child has closed the sync pipe, meaning it's not going to be
        capturing any more packets.  Pick up its exit status, and
-       complain if it died of a signal. */
-#ifdef _WIN32
-    /* XXX - analyze the wait stuatus and display more information
-       in the dialog box? */
-    if (_cwait(&wstatus, child_process, _WAIT_CHILD) == -1) {
-      simple_dialog(ESD_TYPE_WARN, NULL, "Child capture process stopped unexpectedly");
-    }
-#else
-    if (wait(&wstatus) != -1) {
-      /* XXX - are there any platforms on which we can run that *don't*
-         support POSIX.1's <sys/wait.h> and macros therein? */
-      wsignal = wstatus & 0177;
-      coredumped = "";
-      if (wstatus == 0177) {
-       /* It stopped, rather than exiting.  "Should not happen." */
-       msg = "stopped";
-       wsignal = (wstatus >> 8) & 0xFF;
-      } else {
-        msg = "terminated";
-        if (wstatus & 0200)
-          coredumped = " - core dumped";
-      }
-      if (wsignal != 0) {
-        switch (wsignal) {
-
-        case SIGHUP:
-          sigmsg = "Hangup";
-          break;
-
-        case SIGINT:
-          sigmsg = "Interrupted";
-          break;
-
-        case SIGQUIT:
-          sigmsg = "Quit";
-          break;
-
-        case SIGILL:
-          sigmsg = "Illegal instruction";
-          break;
-
-        case SIGTRAP:
-          sigmsg = "Trace trap";
-          break;
-
-        case SIGABRT:
-          sigmsg = "Abort";
-          break;
-
-        case SIGFPE:
-          sigmsg = "Arithmetic exception";
-          break;
-
-        case SIGKILL:
-          sigmsg = "Killed";
-          break;
-
-        case SIGBUS:
-          sigmsg = "Bus error";
-          break;
-
-        case SIGSEGV:
-          sigmsg = "Segmentation violation";
-          break;
-
-       /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO 
-               Linux is POSIX compliant.  These are not POSIX-defined signals ---
-                 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
-
-              ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
-               were omitted from POSIX.1 because their behavior is
-               implementation dependent and could not be adequately catego-
-               rized.  Conforming implementations may deliver these sig-
-               nals, but must document the circumstances under which they
-               are delivered and note any restrictions concerning their
-               delivery.''
-       */
-
-       #ifdef SIGSYS
-        case SIGSYS:
-          sigmsg = "Bad system call";
-          break;
-       #endif
-
-        case SIGPIPE:
-          sigmsg = "Broken pipe";
-          break;
-
-        case SIGALRM:
-          sigmsg = "Alarm clock";
-          break;
-
-        case SIGTERM:
-          sigmsg = "Terminated";
-          break;
-
-        default:
-          sprintf(sigmsg_buf, "Signal %d", wsignal);
-          sigmsg = sigmsg_buf;
-          break;
-        }
-       simple_dialog(ESD_TYPE_WARN, NULL,
-               "Child capture process %s: %s%s", msg, sigmsg, coredumped);
-      }
-    }
-#endif
+       complain if it did anything other than exit with status 0. */
+    wait_for_child(FALSE);
       
     /* Read what remains of the capture file, and finish the capture.
        XXX - do something if this fails? */
@@ -789,6 +712,142 @@ cap_file_input_cb(gpointer data, gint source, GdkInputCondition condition)
 #endif
 }
 
+static void
+wait_for_child(gboolean always_report)
+{
+  int  wstatus;
+
+#ifdef _WIN32
+  /* XXX - analyze the wait stuatus and display more information
+     in the dialog box? */
+  if (_cwait(&wstatus, child_process, _WAIT_CHILD) == -1) {
+    simple_dialog(ESD_TYPE_WARN, NULL, "Child capture process stopped unexpectedly");
+  }
+#else
+  if (wait(&wstatus) != -1) {
+    if (WIFEXITED(wstatus)) {
+      /* The child exited; display its exit status, if it's not zero,
+         and even if it's zero if "always_report" is true. */
+      if (always_report || WEXITSTATUS(wstatus) != 0) {
+        simple_dialog(ESD_TYPE_WARN, NULL,
+                     "Child capture process exited: exit status %d",
+                     WEXITSTATUS(wstatus));
+      }
+    } else if (WIFSTOPPED(wstatus)) {
+      /* It stopped, rather than exiting.  "Should not happen." */
+      simple_dialog(ESD_TYPE_WARN, NULL,
+                   "Child capture process stopped: %s",
+                   signame(WSTOPSIG(wstatus)));
+    } else if (WIFSIGNALED(wstatus)) {
+      /* It died with a signal. */
+      simple_dialog(ESD_TYPE_WARN, NULL,
+                   "Child capture process died: %s%s",
+                   signame(WTERMSIG(wstatus)),
+                   WCOREDUMP(wstatus) ? " - core dumped" : "");
+    } else {
+      /* What?  It had to either have exited, or stopped, or died with
+         a signal; what happened here? */
+      simple_dialog(ESD_TYPE_WARN, NULL,
+                   "Child capture process died: wait status %#o", wstatus);
+    }
+  }
+#endif
+}
+
+#ifndef _WIN32
+static char *
+signame(int sig)
+{
+  char *sigmsg;
+  static char sigmsg_buf[6+1+3+1];
+
+  switch (sig) {
+
+  case SIGHUP:
+    sigmsg = "Hangup";
+    break;
+
+  case SIGINT:
+    sigmsg = "Interrupted";
+    break;
+
+  case SIGQUIT:
+    sigmsg = "Quit";
+    break;
+
+  case SIGILL:
+    sigmsg = "Illegal instruction";
+    break;
+
+  case SIGTRAP:
+    sigmsg = "Trace trap";
+    break;
+
+  case SIGABRT:
+    sigmsg = "Abort";
+    break;
+
+  case SIGFPE:
+    sigmsg = "Arithmetic exception";
+    break;
+
+  case SIGKILL:
+    sigmsg = "Killed";
+    break;
+
+  case SIGBUS:
+    sigmsg = "Bus error";
+    break;
+
+  case SIGSEGV:
+    sigmsg = "Segmentation violation";
+    break;
+
+  /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO 
+     Linux is POSIX compliant.  These are not POSIX-defined signals ---
+     ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
+
+       ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
+       were omitted from POSIX.1 because their behavior is
+       implementation dependent and could not be adequately catego-
+       rized.  Conforming implementations may deliver these sig-
+       nals, but must document the circumstances under which they
+       are delivered and note any restrictions concerning their
+       delivery.''
+
+     So we only check for SIGSYS on those systems that happen to
+     implement them (a system can be POSIX-compliant and implement
+     them, it's just that POSIX doesn't *require* a POSIX-compliant
+     system to implement them).
+   */
+
+#ifdef SIGSYS
+  case SIGSYS:
+    sigmsg = "Bad system call";
+    break;
+#endif
+
+  case SIGPIPE:
+    sigmsg = "Broken pipe";
+    break;
+
+  case SIGALRM:
+    sigmsg = "Alarm clock";
+    break;
+
+  case SIGTERM:
+    sigmsg = "Terminated";
+    break;
+
+  default:
+    sprintf(sigmsg_buf, "Signal %d", sig);
+    sigmsg = sigmsg_buf;
+    break;
+  }
+  return sigmsg;
+}
+#endif
+
 /*
  * Timeout, in milliseconds, for reads from the stream of captured packets.
  */