aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2016-04-27 12:14:11 -0700
committerGerald Combs <gerald@wireshark.org>2016-04-27 23:11:34 +0000
commite5f4c5c8a80e2f5970b8c1d4fdfc29ab851f0e6f (patch)
treef1c26c89c7cae3dcc468508ab61a742853e7d631
parentab6c9f2e2b8898a1592dafacd34cf1fff7ef20b3 (diff)
Windows: Wait for dumpcap to initialize.
As the MSDN documentation says, "CreateProcess returns without waiting for the new process to finish its initialization." Add an SP_INIT sync pipe indicator on Windows and use it in dumpcap to signal to its parent that it has started up. Change-Id: I88a4c158871dbe2dd6eba13434e92c5d4b1c2e4b Reviewed-on: https://code.wireshark.org/review/15132 Reviewed-by: Gerald Combs <gerald@wireshark.org>
-rw-r--r--capchild/capture_sync.c33
-rw-r--r--dumpcap.c2
-rw-r--r--sync_pipe.h1
3 files changed, 34 insertions, 2 deletions
diff --git a/capchild/capture_sync.c b/capchild/capture_sync.c
index edd0c5de7a..9d4ab636e2 100644
--- a/capchild/capture_sync.c
+++ b/capchild/capture_sync.c
@@ -98,12 +98,11 @@
#include <process.h> /* For spawning child process */
#endif
-
-
#ifdef _WIN32
static void create_dummy_signal_pipe();
static HANDLE dummy_signal_pipe; /* Dummy named pipe which lets the child check for a dropped connection */
static gchar *dummy_control_id;
+static gboolean pipe_wait_for_init(int pipe_fd);
#else
static const char *sync_pipe_signame(int);
#endif
@@ -696,6 +695,10 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf
g_free( (gpointer) argv);
return FALSE;
}
+ if (!pipe_wait_for_init(sync_pipe_read_fd)) {
+ return FALSE;
+ }
+
cap_session->fork_child = pi.hProcess;
/* We may need to store this and close it later */
CloseHandle(pi.hThread);
@@ -950,6 +953,10 @@ sync_pipe_open_command(char** argv, int *data_read_fd,
g_free( (gpointer) argv);
return -1;
}
+ if (!pipe_wait_for_init(*message_read_fd)) {
+ return -1;
+ }
+
*fork_child = pi.hProcess;
/* We may need to store this and close it later */
CloseHandle(pi.hThread);
@@ -1716,6 +1723,28 @@ pipe_convert_header(const guchar *header, int header_len, char *indicator, int *
*block_len = (header[1]&0xFF)<<16 | (header[2]&0xFF)<<8 | (header[3]&0xFF);
}
+#ifdef _WIN32
+/* CreateProcess returns immediately. Wait for the child process to send
+ us SP_INIT. Note that WaitForInputIdle is the wrong call to use here
+ as it only applies to GUI applications:
+ https://blogs.msdn.microsoft.com/oldnewthing/20100325-00/?p=14493
+ */
+gboolean
+pipe_wait_for_init(int pipe_fd) {
+ char indicator;
+ char buffer[SP_MAX_MSG_LEN+1] = {0};
+ char *primary_msg;
+
+ pipe_read_block(pipe_fd, &indicator, SP_MAX_MSG_LEN, buffer, &primary_msg);
+ if (indicator != SP_INIT) {
+ report_failure("Child sent startup indicator '%c', expected '%c'.",
+ indicator, SP_INIT);
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
/* read a message from the sending pipe in the standard format
(1-byte message indicator, 3-byte message length (excluding length
and indicator field), and the rest is the message) */
diff --git a/dumpcap.c b/dumpcap.c
index 21230b7ec7..20389eaa0d 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -4131,6 +4131,8 @@ main(int argc, char *argv[])
exit_main(1);
}
}
+ /* Let our parent know we're fully initialized. */
+ pipe_write_block(2, SP_INIT, "All systems go.");
#endif
break;
diff --git a/sync_pipe.h b/sync_pipe.h
index 455b2b4bd6..0fac40b5f0 100644
--- a/sync_pipe.h
+++ b/sync_pipe.h
@@ -62,6 +62,7 @@
* Win32 only: Indications sent out on the signal pipe (from parent to child)
* (UNIX-like sends signals for this)
*/
+#define SP_INIT 'I' /* child process initialized */
#define SP_QUIT 'Q' /* "gracefully" capture quit message (SIGUSR1) */
/* write a single message header to the recipient pipe */