diff options
author | Gerald Combs <gerald@wireshark.org> | 2019-03-01 15:49:52 -0800 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2019-03-04 18:35:41 +0000 |
commit | 69460d44ea7b8883bbe8140868e3ccf4e7dbb981 (patch) | |
tree | b006d69c64990bf023539aa59bf56e518e83edde /epan/maxmind_db.c | |
parent | 9887fe3d15210b67c0d73df77923744dfb8bb267 (diff) |
maxmind_db: Work around an apparent GLib bug.
g_async_queue_timeout_pop can return immediately on macOS and possibly
other OSes when using older versions of GLib. Replace it with
g_async_queue_pop and a "stop" sentinel value.
Bug: 15545
Change-Id: Id0bfacd4a94ec9645d2d27ba92d3a2f48e7d5f37
Reviewed-on: https://code.wireshark.org/review/32289
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Diffstat (limited to 'epan/maxmind_db.c')
-rw-r--r-- | epan/maxmind_db.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/epan/maxmind_db.c b/epan/maxmind_db.c index a0086b3569..e0424acc6e 100644 --- a/epan/maxmind_db.c +++ b/epan/maxmind_db.c @@ -43,6 +43,8 @@ static mmdb_lookup_t mmdb_not_found; static GThread *write_mmdbr_stdin_thread; static GAsyncQueue *mmdbr_request_q; // g_allocated char * +static char mmdbr_stop_sentinel[] = "\x04"; // ASCII EOT. Could be anything. + // The GLib documentation says that g_rw_lock_reader_lock can be called // recursively: // https://developer.gnome.org/glib/stable/glib-Threads.html#g-rw-lock-reader-lock @@ -158,7 +160,6 @@ static gboolean mmdbr_pipe_valid(void) { } // Writing to mmdbr_pipe.stdin_fd can block. Do so in a separate thread. -#define MMDB_WAIT_TIME (150 * 1000) // microseconds static gpointer write_mmdbr_stdin_worker(gpointer sifd_data) { int stdin_fd = GPOINTER_TO_INT(sifd_data); @@ -172,8 +173,15 @@ write_mmdbr_stdin_worker(gpointer sifd_data) { return NULL; } - char *request = (char *) g_async_queue_timeout_pop(mmdbr_request_q, MMDB_WAIT_TIME); - if (!request) { + // On some operating systems (most notably macOS), g_async_queue_timeout_pop + // will return immediately if we've been built with an older version of GLib: + // https://bugzilla.gnome.org/show_bug.cgi?id=673607 + // Call g_async_queue_pop instead. When we need to stop processing, + // mmdb_resolve_stop will close our pipe and then push an invalid address + // (mmdbr_stop_sentinel) onto the queue. + char *request = (char *) g_async_queue_pop(mmdbr_request_q); + if (!request || strcmp(request, mmdbr_stop_sentinel) == 0) { + g_free(request); continue; } @@ -212,6 +220,7 @@ static ssize_t mmdbr_pipe_read_one(char *ch_p) { // - Stash our worker thread handles on Windows and call CancelSynchronousIo // before shutting down our threads. #define MAX_MMDB_LINE_LEN 2000 +#define MMDB_WAIT_TIME (150 * 1000) // microseconds static gpointer read_mmdbr_stdout_worker(gpointer data _U_) { mmdb_response_t *response = g_new0(mmdb_response_t, 1); @@ -374,12 +383,18 @@ static void mmdb_resolve_stop(void) { MMDB_DEBUG("closing pid %d", mmdbr_pipe.pid); ws_pipe_close(&mmdbr_pipe); + g_async_queue_push(mmdbr_request_q, g_strdup(mmdbr_stop_sentinel)); + MMDB_DEBUG("closing pipe FDs"); ws_close(mmdbr_pipe.stdin_fd); ws_close(mmdbr_pipe.stdout_fd); + // read_mmdbr_stdout_worker should exit + g_rw_lock_writer_unlock(&mmdbr_pipe_mtx); + // write_mmdbr_stdin_worker should exit + g_thread_join(write_mmdbr_stdin_thread); write_mmdbr_stdin_thread = NULL; |