Add a routine to kill a capture child if it exists, so that if we exit

(by deleting the main window or selecting File->Quit or typing ^Q) while
an "Update list of packets in real time" capture is in progress, we can
abort the capture.

Arrange that "fork_child" is -1 when there is no capture child, so said
routine knows when it can kill the child.

When we exit, kill off any capture child, using that routine, and, if
we're exiting due to a request to delete the main window and, if a read
is in progress (from an "Update list of packets in real time" capture),
don't delete the main window - just set the "Read aborted" flag, so that
the code doing the read will see that flag (it will be called because
the pipe to the capture child is closed due to the child exiting) will
see that and clean up and exit itself.

svn path=/trunk/; revision=4498
This commit is contained in:
Guy Harris 2002-01-08 09:32:15 +00:00
parent 86a251065d
commit 12d566c0ac
3 changed files with 69 additions and 32 deletions

View File

@ -1,7 +1,7 @@
/* capture.c
* Routines for packet capture windows
*
* $Id: capture.c,v 1.165 2002/01/04 06:27:42 guy Exp $
* $Id: capture.c,v 1.166 2002/01/08 09:32:14 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -173,7 +173,7 @@ static int sync_pipe[2]; /* used to sync father */
enum PIPES { READ, WRITE }; /* Constants 0 and 1 for READ and WRITE */
int quit_after_cap; /* Makes a "capture only mode". Implies -k */
gboolean capture_child; /* if this is the child for "-S" */
static int fork_child; /* In parent, process ID of child */
static int fork_child = -1; /* If not -1, in parent, process ID of child */
static guint cap_input_id;
/*
@ -893,6 +893,9 @@ wait_for_child(gboolean always_report)
"Child capture process died: wait status %#o", wstatus);
}
}
/* No more child process. */
fork_child = -1;
#endif
}
@ -1963,6 +1966,18 @@ capture_stop(void)
#endif
}
void
kill_capture_child(void)
{
/*
* XXX - find some way of signaling the child in Win32.
*/
#ifndef _WIN32
if (fork_child != -1)
kill(fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
#endif
}
static void
capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
const u_char *pd) {

View File

@ -1,7 +1,7 @@
/* capture.h
* Definitions for packet capture windows
*
* $Id: capture.h,v 1.26 2001/04/13 14:59:28 jfoster Exp $
* $Id: capture.h,v 1.27 2002/01/08 09:32:14 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -45,6 +45,9 @@ int capture(gboolean *stats_known, struct pcap_stat *stats);
/* Stop a capture from a menu item. */
void capture_stop(void);
/* Terminate the capture child cleanly when exiting. */
void kill_capture_child(void);
#endif /* HAVE_LIBPCAP */
#define EMPTY_FILTER ""

View File

@ -1,6 +1,6 @@
/* main.c
*
* $Id: main.c,v 1.222 2001/12/31 04:41:50 gerald Exp $
* $Id: main.c,v 1.223 2002/01/08 09:32:15 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -734,31 +734,7 @@ statusbar_pop_field_msg(void)
}
static gboolean
main_window_delete_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
{
gint desk_x, desk_y;
/* Try to grab our geometry */
gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
if (gdk_window_get_deskrelative_origin(top_level->window,
&desk_x, &desk_y)) {
if (desk_x <= root_x && desk_y <= root_y) {
root_x = desk_x;
root_y = desk_y;
}
}
/* XXX - Is this the "approved" method? */
gdk_window_get_size(top_level->window, &top_width, &top_height);
file_quit_cmd_cb(widget, data);
/* Say that the window should be deleted. */
return FALSE;
}
void
file_quit_cmd_cb (GtkWidget *widget, gpointer data)
do_quit(void)
{
/* XXX - should we check whether the capture file is an
unsaved temporary file for a live capture and, if so,
@ -767,9 +743,17 @@ file_quit_cmd_cb (GtkWidget *widget, gpointer data)
box to forcibly quit if the user clicks "OK"?
If so, note that this should be done in a subroutine that
returns TRUE if we do so, and FALSE otherwise, and that
"main_window_delete_event_cb()" should return its
return value. */
returns TRUE if we do so, and FALSE otherwise, and if it
returns TRUE we should return TRUE without nuking anything.
Note that, if we do that, we might also want to check if
an "Update list of packets in real time" capture is in
progress and, if so, ask whether they want to terminate
the capture and discard it, and return TRUE, before nuking
any child capture, if they say they don't want to do so. */
/* Nuke any child capture in progress. */
kill_capture_child();
/* Are we in the middle of reading a capture? */
if (cfile.state == FILE_READ_IN_PROGRESS) {
@ -780,6 +764,10 @@ file_quit_cmd_cb (GtkWidget *widget, gpointer data)
will check for that and, if it sees that, will clean
up and quit. */
cfile.state = FILE_READ_ABORTED;
/* Say that the window should *not* be deleted;
that'll be done by the code that cleans up. */
return TRUE;
} else {
/* Close any capture file we have open; on some OSes, you
can't unlink a temporary capture file if you have it
@ -806,9 +794,40 @@ file_quit_cmd_cb (GtkWidget *widget, gpointer data)
/* Exit by leaving the main loop, so that any quit functions
we registered get called. */
gtk_main_quit();
/* Say that the window should be deleted. */
return FALSE;
}
}
static gboolean
main_window_delete_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
{
gint desk_x, desk_y;
/* Try to grab our geometry */
gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
if (gdk_window_get_deskrelative_origin(top_level->window,
&desk_x, &desk_y)) {
if (desk_x <= root_x && desk_y <= root_y) {
root_x = desk_x;
root_y = desk_y;
}
}
/* XXX - Is this the "approved" method? */
gdk_window_get_size(top_level->window, &top_width, &top_height);
/* "do_quit()" indicates whether the main window should be deleted. */
return do_quit();
}
void
file_quit_cmd_cb (GtkWidget *widget, gpointer data)
{
do_quit();
}
static void
print_usage(void) {