diff options
author | Gerald Combs <gerald@wireshark.org> | 2012-08-24 15:25:42 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2012-08-24 15:25:42 +0000 |
commit | 5f2783de056b0e9f5c219cba3317eb69734f6b3b (patch) | |
tree | c46b3457c5ac237b871c02b0a2f19b2be406e6b5 /ui/gtk/gui_utils.c | |
parent | 64d81e7477ec32dec9fa48facb5a4024e7bc5ab2 (diff) |
Revert r44644 and 44645. g_source_*, g_timeout_, and g_io_* all depend
on the GLib main loop which isn't portable (unless you want to want to
manage the main loop yourself).
svn path=/trunk/; revision=44655
Diffstat (limited to 'ui/gtk/gui_utils.c')
-rw-r--r-- | ui/gtk/gui_utils.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/ui/gtk/gui_utils.c b/ui/gtk/gui_utils.c index f4b9ce3054..f9cdd804f9 100644 --- a/ui/gtk/gui_utils.c +++ b/ui/gtk/gui_utils.c @@ -642,6 +642,151 @@ void main_window_quit(void) gtk_main_quit(); } + + +typedef struct pipe_input_tag { + gint source; + gpointer user_data; + int *child_process; + pipe_input_cb_t input_cb; + guint pipe_input_id; +#ifdef _WIN32 +#else + GIOChannel *channel; +#endif +} pipe_input_t; + + +#ifdef _WIN32 +/* The timer has expired, see if there's stuff to read from the pipe, + if so, do the callback */ +static gboolean +pipe_timer_cb(gpointer data) +{ + HANDLE handle; + DWORD avail = 0; + gboolean result, result1; + DWORD childstatus; + pipe_input_t *pipe_input = data; + gint iterations = 0; + + + /* try to read data from the pipe only 5 times, to avoid blocking */ + while(iterations < 5) { + /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: new iteration");*/ + + /* Oddly enough although Named pipes don't work on win9x, + PeekNamedPipe does !!! */ + handle = (HANDLE) _get_osfhandle (pipe_input->source); + result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL); + + /* Get the child process exit status */ + result1 = GetExitCodeProcess((HANDLE)*(pipe_input->child_process), + &childstatus); + + /* If the Peek returned an error, or there are bytes to be read + or the childwatcher thread has terminated then call the normal + callback */ + if (!result || avail > 0 || childstatus != STILL_ACTIVE) { + + /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: data avail");*/ + + if(pipe_input->pipe_input_id != 0) { + /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: stop timer");*/ + /* avoid reentrancy problems and stack overflow */ + g_source_remove(pipe_input->pipe_input_id); + pipe_input->pipe_input_id = 0; + } + + /* And call the real handler */ + if (!pipe_input->input_cb(pipe_input->source, pipe_input->user_data)) { + g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations); + /* pipe closed, return false so that the old timer is not run again */ + return FALSE; + } + } + else { + /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: no data avail");*/ + /* No data, stop now */ + break; + } + + iterations++; + } + + if(pipe_input->pipe_input_id == 0) { + /* restore pipe handler */ + pipe_input->pipe_input_id = g_timeout_add(200, pipe_timer_cb, data); + /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: finished with iterations: %u, new timer", iterations);*/ + + /* Return false so that the old timer is not run again */ + return FALSE; + } else { + /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: finished with iterations: %u, old timer", iterations);*/ + + /* we didn't stopped the old timer, so let it run */ + return TRUE; + } +} + +#else /* _WIN32 */ + +/* 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). */ +static gboolean +pipe_input_cb(GIOChannel *source _U_, GIOCondition condition _U_, + gpointer data) +{ + pipe_input_t *pipe_input = data; + + + /* avoid reentrancy problems and stack overflow */ + g_source_remove(pipe_input->pipe_input_id); + + if (pipe_input->input_cb(pipe_input->source, pipe_input->user_data)) { + /* restore pipe handler */ + pipe_input->pipe_input_id = g_io_add_watch_full (pipe_input->channel, + G_PRIORITY_HIGH, + G_IO_IN|G_IO_ERR|G_IO_HUP, + pipe_input_cb, + pipe_input, + NULL); + } + return TRUE; +} +#endif + +void pipe_input_set_handler(gint source, gpointer user_data, int *child_process, pipe_input_cb_t input_cb) +{ + static pipe_input_t pipe_input; + + pipe_input.source = source; + pipe_input.child_process = child_process; + pipe_input.user_data = user_data; + pipe_input.input_cb = input_cb; + +#ifdef _WIN32 + /* Tricky to use pipes in win9x, as no concept of wait. NT can + do this but that doesn't cover all win32 platforms. GTK can do + this but doesn't seem to work over processes. Attempt to do + something similar here, start a timer and check for data on every + timeout. */ + /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_input_set_handler: new");*/ + pipe_input.pipe_input_id = g_timeout_add(200, pipe_timer_cb, &pipe_input); +#else + pipe_input.channel = g_io_channel_unix_new(source); + g_io_channel_set_encoding(pipe_input.channel, NULL, NULL); + pipe_input.pipe_input_id = g_io_add_watch_full(pipe_input.channel, + G_PRIORITY_HIGH, + G_IO_IN|G_IO_ERR|G_IO_HUP, + pipe_input_cb, + &pipe_input, + NULL); +#endif +} + + #endif /* HAVE_LIBPCAP */ /* Given a pointer to a GtkWidget for a top-level window, raise it and |