keywords and eol-style
[obnox/wireshark/wip.git] / capture_sync.c
index ab77f3352b38f1d6010f50ca10519214fba6eac5..9c177afe67076081e36e6c14ddf4348abb838856 100644 (file)
@@ -87,6 +87,7 @@
 #include "capture-wpcap.h"
 #endif
 #include "ui_util.h"
+#include "log.h"
 
 #ifdef HAVE_IO_H
 # include <io.h>
@@ -107,9 +108,8 @@ static char *sync_pipe_signame(int);
 #endif
 
 
-static gboolean sync_pipe_input_wait_for_start(capture_options *capture_opts, int sync_pipe_read);
 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
-static void sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report);
+static void sync_pipe_wait_for_child(capture_options *capture_opts);
 
 /* Size of buffer to hold decimal representation of
    signed/unsigned 64-bit int */
@@ -118,70 +118,163 @@ static void sync_pipe_wait_for_child(capture_options *capture_opts, gboolean alw
 /*
  * Indications sent out on the sync pipe.
  */
-#define SP_CAPSTART     ';'    /* capture start message */
-#define SP_PACKET_COUNT '*'     /* followed by count of packets captured since last message */
-#define SP_ERROR_MSG    '!'     /* followed by length of error message that follows */
-#define SP_DROPS        '#'    /* followed by count of packets dropped in capture */
-#define SP_FILE                ':'     /* followed by length of the name of the last opened file that follows */
+#define SP_FILE                'F'         /* the name of the recently opened file */
+#define SP_ERROR_MSG    'E'     /* error message */
+#define SP_PACKET_COUNT 'P'     /* count of packets captured since last message */
+#define SP_DROPS        'D'        /* count of packets dropped in capture */
+#define SP_QUIT         'Q'     /* capture quit message (from parent to child) */
 
 
-
-void
-sync_pipe_capstart_to_parent(void)
+/* write a message to the recipient pipe in the standard format 
+   (3 digit message length (excluding length and indicator field), 
+   1 byte message indicator and the rest is the message) */
+static void
+pipe_write_block(int pipe, char indicator, int len, const char *msg)
 {
-    static const char capstart_msg = SP_CAPSTART;
+    char lenbuf[3+1+1]; /* 3 digit len + indicator + zero terminator */
+    int ret;
+
+    /*g_warning("write %d enter", pipe);*/
+
+    g_assert(len < 1000);
+    g_assert(indicator < '0' || indicator > '9');
+
+    /* write header (3 digit len + indicator) */
+    g_snprintf(lenbuf, 5, "%03u%c", len, indicator);
+
+    ret = write(pipe, lenbuf, strlen(lenbuf));
+    if(ret == -1) {
+        return;
+    }
+
+    /* write value (if we have one) */
+    if(len) {
+        /*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
+        ret = write(pipe, msg, len);
+        if(ret == -1) {
+            return;
+        }
+    } else {
+        /*g_warning("write %d indicator: %c no value", pipe, indicator);*/
+    }
 
-    write(1, &capstart_msg, 1);
+    /*g_warning("write %d leave", pipe);*/
+}
+
+
+/* read a message from the sending pipe in the standard format 
+   (3 digit message length (excluding length and indicator field), 
+   1 byte message indicator and the rest is the message) */
+int
+pipe_read_block(int pipe, char *indicator, int len, char *msg) {
+    int required;
+    int newly;
+    char header[4];
+    int offset;
+
+
+    /* read header (3 digit len and indicator) */
+    required = 4;
+    offset = 0;
+    while(required) {
+        newly = read(pipe, &header[offset], required);
+        if (newly == 0) {
+            /* EOF */
+            /*g_warning("read %d header empty (capture closed)", pipe);*/
+            return newly;
+        }
+        if (newly < 0) {
+            /* error */
+            /*g_warning("read %d header error: %s", pipe, strerror(errno));*/
+            return newly;
+        }
+
+        required -= newly;
+        offset += newly;
+    }
+
+    /* convert header values */
+    *indicator = header[3];
+    required = atoi(header);
+
+    /* only indicator with no value? */
+    if(required == 0) {
+        /*g_warning("read %d indicator: %c empty value", pipe, *indicator);*/
+        return 4;
+    }
+
+    g_assert(required <= len);
+    len = required;
+
+    /* read value */
+    offset = 0;
+    while(required) {
+        newly = read(pipe, &msg[offset], required);
+        if (newly == -1) {
+            /* error */
+            /*g_warning("read %d value error, indicator: %u", pipe, *indicator);*/
+            return newly;
+        }
+
+        required -= newly;
+        offset += newly;
+    }
+
+    /*g_warning("read %d ok indicator: %c len: %u msg: %s", pipe, *indicator, len, msg);*/
+    return len + 4;
 }
 
 void
 sync_pipe_packet_count_to_parent(int packet_count)
 {
     char tmp[SP_DECISIZE+1+1];
-    sprintf(tmp, "%d%c", packet_count, SP_PACKET_COUNT);
-    write(1, tmp, strlen(tmp));
+
+    g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
+
+    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_packet_count_to_parent: %s", tmp);
+
+    pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
 }
 
 void
 sync_pipe_filename_to_parent(const char *filename)
 {
-    int msglen = strlen(filename);
-    char lenbuf[SP_DECISIZE+1+1];
+    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_filename_to_parent: %s", filename);
 
-    sprintf(lenbuf, "%u%c", msglen, SP_FILE);
-    write(1, lenbuf, strlen(lenbuf));
-    write(1, filename, msglen);
+    pipe_write_block(1, SP_FILE, strlen(filename)+1, filename);
 }
 
 void
 sync_pipe_errmsg_to_parent(const char *errmsg)
 {
-    int msglen = strlen(errmsg);
-    char lenbuf[SP_DECISIZE+1+1];
+    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
 
-    sprintf(lenbuf, "%u%c", msglen, SP_ERROR_MSG);
-    write(1, lenbuf, strlen(lenbuf));
-    write(1, errmsg, msglen);
+    pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
 }
 
 void
 sync_pipe_drops_to_parent(int drops)
 {
        char tmp[SP_DECISIZE+1+1];
-       sprintf(tmp, "%d%c", drops, SP_DROPS);
-       write(1, tmp, strlen(tmp));
+
+
+    g_snprintf(tmp, sizeof(tmp), "%d", drops);
+
+    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_drops_to_parent: %s", tmp);
+
+    pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
 }
 
 
 #ifdef _WIN32
-#define SP_CAPEND 'q'
 
 static void
-signal_pipe_capend_to_child(capture_options *capture_opts)
+signal_pipe_capquit_to_child(capture_options *capture_opts)
 {
-    static const char capend_msg = SP_CAPEND;
 
-    write(capture_opts->signal_pipe_fd, &capend_msg, 1);
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
+
+    pipe_write_block(capture_opts->signal_pipe_fd, SP_QUIT, 0, NULL);
 }
 #endif
 
@@ -230,7 +323,7 @@ sync_pipe_quote_encapsulate(const char *string)
 #define ARGV_NUMBER_LEN 24
 
 gboolean
-sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
+sync_pipe_start(capture_options *capture_opts) {
     char ssnap[ARGV_NUMBER_LEN];
     char scount[ARGV_NUMBER_LEN];
     char sfilesize[ARGV_NUMBER_LEN];
@@ -240,10 +333,12 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
     char sautostop_filesize[ARGV_NUMBER_LEN];
     char sautostop_duration[ARGV_NUMBER_LEN];
 #ifdef _WIN32
+    char buffer_size[ARGV_NUMBER_LEN];
     char sync_pipe_fd[ARGV_NUMBER_LEN];
     char signal_pipe_fd[ARGV_NUMBER_LEN];
     char *fontstring;
     char *filterstring;
+    char *savefilestring;
     int signal_pipe[2];                     /* pipe used to send messages from parent to child (currently only stop) */
 #else
     char errmsg[1024+1];
@@ -254,8 +349,10 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
     int sync_pipe[2];                       /* pipe used to send messages from child to parent */
 
 
-    /*g_warning("sync_pipe_start");
-    capture_opts_info(capture_opts);*/
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
+#ifdef LOG_CAPTURE_VERBOSE
+    capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
+#endif
 
     capture_opts->fork_child = -1;
 
@@ -271,11 +368,6 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
     argv = sync_pipe_add_arg(argv, &argc, "-i");
     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
 
-    if(capture_opts->save_file) {
-      argv = sync_pipe_add_arg(argv, &argc, "-w");
-      argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
-    }
-
     if (capture_opts->has_snaplen) {
       argv = sync_pipe_add_arg(argv, &argc, "-s");
       sprintf(ssnap,"%d",capture_opts->snaplen);
@@ -346,7 +438,8 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
 
 #ifdef _WIN32
     /* Create a pipe for the child process */
-    if(_pipe(sync_pipe, 512, O_BINARY) < 0) {
+    /* (inrease this value if you have trouble while fast capture file switches) */
+    if(_pipe(sync_pipe, 5120, O_BINARY) < 0) {
       /* Couldn't create the pipe between parent and child. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
                         strerror(errno));
@@ -367,6 +460,10 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
 
     capture_opts->signal_pipe_fd = signal_pipe[PIPE_WRITE];
 
+    argv = sync_pipe_add_arg(argv, &argc, "-B");
+    sprintf(buffer_size,"%d",capture_opts->buffer_size);
+    argv = sync_pipe_add_arg(argv, &argc, buffer_size);
+
     /* Convert font name to a quote-encapsulated string and pass to child */
     argv = sync_pipe_add_arg(argv, &argc, "-m");
     fontstring = sync_pipe_quote_encapsulate(prefs.PREFS_GUI_FONT_NAME);
@@ -390,12 +487,23 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
       argv = sync_pipe_add_arg(argv, &argc, filterstring);
     }
 
+    /* Convert save file name to a quote delimited string and pass to child */
+    savefilestring = NULL;
+    if(capture_opts->save_file) {
+      argv = sync_pipe_add_arg(argv, &argc, "-w");
+      savefilestring = sync_pipe_quote_encapsulate(capture_opts->save_file);
+      argv = sync_pipe_add_arg(argv, &argc, savefilestring);
+    }
+
     /* Spawn process */
     capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
     g_free(fontstring);
     if (filterstring) {
       g_free(filterstring);
     }
+    if(savefilestring) {
+      g_free(savefilestring);
+    }
 
     /* child own's the read side now, close our handle */
     close(signal_pipe[PIPE_READ]);
@@ -416,6 +524,11 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
       argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
     }
 
+    if(capture_opts->save_file) {
+      argv = sync_pipe_add_arg(argv, &argc, "-w");
+      argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
+    }
+
     if ((capture_opts->fork_child = fork()) == 0) {
       /*
        * Child process - run Ethereal with the right arguments to make
@@ -470,16 +583,6 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
     /* we might wait for a moment till child is ready, so update screen now */
     main_window_update();
 
-    /* the child have to send us a capture start or error message now */
-    if(!sync_pipe_input_wait_for_start(capture_opts, sync_pipe[PIPE_READ])) {
-           /* Close the sync pipe. */
-           close(sync_pipe[PIPE_READ]);
-#ifdef _WIN32
-        close(signal_pipe[PIPE_WRITE]);
-#endif
-        return FALSE;
-    }
-
     /* We were able to set up to read the capture file;
        arrange that our callback be called whenever it's possible
        to read from the sync pipe, so that it's called when
@@ -492,77 +595,6 @@ sync_pipe_start(capture_options *capture_opts, gboolean is_tempfile) {
     return TRUE;
 }
 
-
-/* capture prepared, waiting for the child to signal us capture has indeed started */
-static gboolean
-sync_pipe_input_wait_for_start(capture_options *capture_opts, int sync_pipe_read) {
-    guint   byte_count;
-    int     i;
-    guchar  c;
-    char    *msg;
-
-
-    /* Read a byte count from "sync_pipe[PIPE_READ]", terminated with a
-       colon; if the count is 0, the child process created the
-       capture file and we should start reading from it, otherwise
-       the capture couldn't start and the count is a count of bytes
-       of error message, and we should display the message. */
-    byte_count = 0;
-    for (;;) {
-      i = read(sync_pipe_read, &c, 1);
-      if (i == 0) {
-       /* EOF - the child process died, report the failure. */
-       sync_pipe_wait_for_child(capture_opts, TRUE);
-       return FALSE;
-      }
-
-      /* the first message should be the capture start or an error message */
-      if (c == SP_CAPSTART || c == SP_ERROR_MSG)
-       break;
-      if (!isdigit(c)) {
-            /* Child process handed us crap, report the failure. */
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                       "Capture child process sent us a bad message");
-       return FALSE;
-      }
-      byte_count = byte_count*10 + c - '0';
-    }
-    if (c != SP_CAPSTART) {
-      /* Failure - the child process sent us a message indicating
-        what the problem was. */
-      if (byte_count == 0) {
-       /* Zero-length message? */
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-               "Capture child process failed, but its error message was empty.");
-      } else {
-       msg = g_malloc(byte_count + 1);
-       if (msg == NULL) {
-         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-               "Capture child process failed, but its error message was too big.");
-       } else {
-         i = read(sync_pipe_read, msg, byte_count);
-         msg[byte_count] = '\0';
-         if (i < 0) {
-           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                 "Capture child process failed: Error %s reading its error message.",
-                 strerror(errno));
-         } else if (i == 0) {
-           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                 "Capture child process failed: EOF reading its error message.");
-           sync_pipe_wait_for_child(capture_opts, FALSE);
-         } else
-           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
-         g_free(msg);
-       }
-
-      }
-      return FALSE;
-    }
-
-    return TRUE;
-}
-
-
 /* There's stuff to read from the sync pipe, meaning the child has sent
    us a message, or the sync pipe has closed, meaning the child has
    closed it (perhaps because it exited). */
@@ -571,16 +603,20 @@ sync_pipe_input_cb(gint source, gpointer user_data)
 {
   capture_options *capture_opts = (capture_options *)user_data;
 #define BUFSIZE        4096
-  char buffer[BUFSIZE+1], *p = buffer, *q = buffer, *msg, *r;
-  int  nread, msglen, chars_to_copy;
-  int  to_read = 0;
+  char buffer[BUFSIZE+1];
+  int  nread;
+  char indicator;
+
 
+  nread = pipe_read_block(source, &indicator, BUFSIZE, buffer);
+  if(nread <= 0) {
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: child has closed sync_pipe");
 
-  if ((nread = read(source, buffer, BUFSIZE)) <= 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 did anything other than exit with status 0. */
-    sync_pipe_wait_for_child(capture_opts, FALSE);
+    sync_pipe_wait_for_child(capture_opts);
+
 #ifdef _WIN32
     close(capture_opts->signal_pipe_fd);
 #endif
@@ -588,115 +624,56 @@ sync_pipe_input_cb(gint source, gpointer user_data)
     return FALSE;
   }
 
-  buffer[nread] = '\0';
-
-  while (nread != 0) {
-    /* look for (possibly multiple) indications */
-    switch (*q) {
-    case SP_PACKET_COUNT :
-      to_read += atoi(p);
-      p = q + 1;
-      q++;
-      nread--;
-      break;
-    case SP_DROPS :
-      cf_set_drops_known(capture_opts->cf, TRUE);
-      cf_set_drops(capture_opts->cf, atoi(p));
-      p = q + 1;
-      q++;
-      nread--;
-      break;
-    case SP_ERROR_MSG :
-      msglen = atoi(p);
-      p = q + 1;
-      q++;
-      nread--;
-
-      /* Read the entire message.
-         XXX - if the child hasn't sent it all yet, this could cause us
-         to hang until they do. */
-      msg = g_malloc(msglen + 1);
-      r = msg;
-      while (msglen != 0) {
-       if (nread == 0) {
-         /* Read more. */
-          if ((nread = read(source, buffer, BUFSIZE)) <= 0)
-            break;
-          p = buffer;
-          q = buffer;
-        }
-       chars_to_copy = MIN(msglen, nread);
-        memcpy(r, q, chars_to_copy);
-        r += chars_to_copy;
-        q += chars_to_copy;
-        nread -= chars_to_copy;
-        msglen -= chars_to_copy;
+  switch(indicator) {
+  case SP_FILE:
+      if(!capture_input_new_file(capture_opts, buffer)) {
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
+
+        /* We weren't able to open the new capture file; user has been
+           alerted. Close the sync pipe. */
+        /* XXX - is it safe to close the pipe inside this callback? */
+        close(source);
+
+        /* the child has send us a filename which we couldn't open.
+           this probably means, the child is creating files faster than we can handle it.
+           this should only be the case for very fast file switches
+           we can't do much more than telling the child to stop
+           (this is the emergency brake if user e.g. wants to switch files every second) */
+        sync_pipe_stop(capture_opts);
       }
-      *r = '\0';
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
-      g_free(msg);
       break;
-    case SP_FILE :
-      msglen = atoi(p);
-      p = q + 1;
-      q++;
-      nread--;
-
-      /* Read the entire file name.
-         XXX - if the child hasn't sent it all yet, this could cause us
-         to hang until they do. */
-      msg = g_malloc(msglen + 1);
-      r = msg;
-      while (msglen != 0) {
-       if (nread == 0) {
-         /* Read more. */
-          if ((nread = read(source, buffer, BUFSIZE)) <= 0)
-            break;
-          p = buffer;
-          q = buffer;
-        }
-       chars_to_copy = MIN(msglen, nread);
-        memcpy(r, q, chars_to_copy);
-        r += chars_to_copy;
-        q += chars_to_copy;
-        nread -= chars_to_copy;
-        msglen -= chars_to_copy;
-      }
-      *r = '\0';
-
-      if(!capture_input_new_file(capture_opts, msg)) {
-         /* We weren't able to open the new capture file; user has been
-            alerted. Close the sync pipe. */
-/*            close(sync_pipe[PIPE_READ]);*/
-
-            /* XXX - how to kill things here ? */
-            /* XXX - is it safe to close the pipe inside this callback? */
-            close(source);
-      }
-
-      g_free(msg);
-
-      break;
-    default :
-      q++;
-      nread--;
-      break;
-    }
+  case SP_PACKET_COUNT:
+    nread = atoi(buffer);
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
+    capture_input_new_packets(capture_opts, nread);
+    break;
+  case SP_ERROR_MSG:
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\"", buffer);
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
+    /* the capture child will close the sync_pipe, nothing to do for now */
+    break;
+  case SP_DROPS:
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", atoi(buffer), plurality(atoi(buffer), "", "s"));
+    cf_set_drops_known(capture_opts->cf, TRUE);
+    cf_set_drops(capture_opts->cf, atoi(buffer));
+    break;
+  default:
+      g_assert_not_reached();
   }
 
-  capture_input_new_packets(capture_opts, to_read);
-
   return TRUE;
 }
 
 
+
 /* the child process is going down, wait until it's completely terminated */
 static void
-sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report)
+sync_pipe_wait_for_child(capture_options *capture_opts)
 {
   int  wstatus;
 
 
+  g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
   g_assert(capture_opts->fork_child != -1);
 
 #ifdef _WIN32
@@ -710,9 +687,13 @@ sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report)
 #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) {
+      /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
+      /* the child will inform us about errors through the sync_pipe, which will popup */
+      /* an error message, so don't popup another one */
+
+      /* XXX - if there are situations where the child won't send us such an error message, */
+      /* this should be fixed in the child and not here! */
+      if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                      "Child capture process exited: exit status %d",
                      WEXITSTATUS(wstatus));
@@ -739,6 +720,8 @@ sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report)
   /* No more child process. */
   capture_opts->fork_child = -1;
 #endif
+
+  g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
 }
 
 
@@ -850,7 +833,7 @@ sync_pipe_stop(capture_options *capture_opts)
 #else
     /* Win32 doesn't have the kill() system call, use the special signal pipe 
        instead to close the capture child gracefully. */
-    signal_pipe_capend_to_child(capture_opts);
+    signal_pipe_capquit_to_child(capture_opts);
 #endif
   }
 }