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>
This commit is contained in:
Gerald Combs 2019-03-01 15:49:52 -08:00
parent 9887fe3d15
commit 69460d44ea
1 changed files with 18 additions and 3 deletions

View File

@ -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;