From 13a89a846b79145209ac68fcc6295156699e55ea Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Sat, 29 Nov 2008 13:23:52 +0000 Subject: [PATCH] Add assertions about which thread we are running in. --- internal.h | 6 +++++ main.c | 12 ++++++++++ wui_thread.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/internal.h b/internal.h index 2fbf2c7..77b3907 100644 --- a/internal.h +++ b/internal.h @@ -61,6 +61,12 @@ extern gboolean check_cert; extern void start_wui_thread (void); extern void stop_wui_thread (void); +extern void assert_is_main_thread (const char *, int); +extern void assert_is_wui_thread (const char *, int); + +#define ASSERT_IS_MAIN_THREAD() assert_is_main_thread(__FILE__,__LINE__) +#define ASSERT_IS_WUI_THREAD() assert_is_wui_thread(__FILE__,__LINE__) + /* These are messages (instructions) which can be sent from the main * thread to the WUI thread. */ diff --git a/main.c b/main.c index 0545ec4..0425128 100644 --- a/main.c +++ b/main.c @@ -415,6 +415,7 @@ gboolean main_connected (gpointer data) { DEBUG ("connected"); + ASSERT_IS_MAIN_THREAD (); gtk_label_set_text (GTK_LABEL (ca_error), NULL); @@ -429,6 +430,8 @@ gboolean main_disconnected (gpointer data) { DEBUG ("disconnected"); + ASSERT_IS_MAIN_THREAD (); + gtk_widget_show (connection_area); gtk_widget_hide (login_area); return FALSE; @@ -439,6 +442,8 @@ gboolean main_logged_in (gpointer data) { DEBUG ("logged in"); + ASSERT_IS_MAIN_THREAD (); + gtk_widget_hide (login_area); return FALSE; } @@ -448,6 +453,8 @@ gboolean main_logged_out (gpointer data) { DEBUG ("logged out"); + ASSERT_IS_MAIN_THREAD (); + if (wui_thread_is_connected ()) gtk_widget_show (login_area); return FALSE; @@ -460,6 +467,7 @@ main_busy (gpointer data) GdkWindow *gdk_window; DEBUG ("busy"); + ASSERT_IS_MAIN_THREAD (); gdk_window = gtk_widget_get_window (window); if (gdk_window) { @@ -477,6 +485,7 @@ main_idle (gpointer data) GdkWindow *gdk_window; DEBUG ("idle"); + ASSERT_IS_MAIN_THREAD (); gdk_window = gtk_widget_get_window (window); if (gdk_window) { @@ -496,6 +505,7 @@ main_connection_error (gpointer _str) char *str = (char *) _str; DEBUG ("connection error: %s", str); + ASSERT_IS_MAIN_THREAD (); gtk_label_set_text (GTK_LABEL (ca_error), str); g_free (str); @@ -512,6 +522,7 @@ main_login_error (gpointer _str) char *str = (char *) _str; DEBUG ("login error: %s", str); + ASSERT_IS_MAIN_THREAD (); /* gtk_label_set_text (GTK_LABEL (ca_error), str); @@ -530,6 +541,7 @@ main_status_error (gpointer _str) char *str = (char *) _str; DEBUG ("status error: %s", str); + ASSERT_IS_MAIN_THREAD (); /* gtk_label_set_text (GTK_LABEL (ca_error), str); diff --git a/wui_thread.c b/wui_thread.c index 49dc270..94631b6 100644 --- a/wui_thread.c +++ b/wui_thread.c @@ -64,6 +64,7 @@ struct message { /* Start the WUI thread. See main() for explanation of the threading model. */ static GThread *wui_gthread = NULL; +static GThread *main_gthread = NULL; static GAsyncQueue *wui_thread_queue = NULL; void @@ -73,6 +74,10 @@ start_wui_thread (void) DEBUG ("starting the WUI thread"); + assert (wui_gthread == NULL); + + main_gthread = g_thread_self (); + /* Create the message queue for main -> WUI thread communications. */ wui_thread_queue = g_async_queue_new (); @@ -88,7 +93,9 @@ void stop_wui_thread (void) { DEBUG ("stopping the WUI thread"); - assert (wui_gthread); + + assert (wui_gthread != NULL); + ASSERT_IS_MAIN_THREAD (); /* Send a quit message then wait for the WUI thread to join. * @@ -107,12 +114,32 @@ stop_wui_thread (void) wui_gthread = NULL; } +void +assert_is_wui_thread (const char *filename, int lineno) +{ + if (g_thread_self () != wui_gthread) { + fprintf (stderr, "%s:%d: internal error: this function should only run in the context of the WUI thread\n", filename, lineno); + abort (); + } +} + +void +assert_is_main_thread (const char *filename, int lineno) +{ + if (g_thread_self () != main_gthread) { + fprintf (stderr, "%s:%d: internal error: this function should only run in the context of the main thread\n", filename, lineno); + abort (); + } +} + /* Send the quit message to the WUI thread. */ static void wui_thread_send_quit (void) { struct message *msg; + ASSERT_IS_MAIN_THREAD (); + msg = g_new (struct message, 1); msg->type = QUIT; g_async_queue_push (wui_thread_queue, msg); @@ -124,6 +151,8 @@ wui_thread_send_connect (const char *uri) { struct message *msg; + ASSERT_IS_MAIN_THREAD (); + msg = g_new (struct message, 1); msg->type = CONNECT; msg->str1 = g_strdup (uri); @@ -136,6 +165,8 @@ wui_thread_send_disconnect (void) { struct message *msg; + ASSERT_IS_MAIN_THREAD (); + msg = g_new (struct message, 1); msg->type = DISCONNECT; g_async_queue_push (wui_thread_queue, msg); @@ -147,6 +178,8 @@ wui_thread_send_login (const char *username, const char *password) { struct message *msg; + ASSERT_IS_MAIN_THREAD (); + msg = g_new (struct message, 1); msg->type = LOGIN; msg->str1 = g_strdup (username); @@ -160,6 +193,8 @@ wui_thread_send_refresh_vm_list (void) { struct message *msg; + ASSERT_IS_MAIN_THREAD (); + msg = g_new (struct message, 1); msg->type = REFRESH_VM_LIST; g_async_queue_push (wui_thread_queue, msg); @@ -205,6 +240,8 @@ wui_thread (gpointer _queue) DEBUG ("WUI thread starting up"); + ASSERT_IS_WUI_THREAD (); + g_async_queue_ref (queue); /* In the thread's loop we check for new instructions from the main @@ -254,6 +291,8 @@ wui_thread (gpointer _queue) static void set_connected (gboolean new_connected) { + ASSERT_IS_WUI_THREAD (); + g_static_mutex_lock (&state_mutex); connected = new_connected; g_static_mutex_unlock (&state_mutex); @@ -267,6 +306,8 @@ set_connected (gboolean new_connected) static void set_logged_in (gboolean new_logged_in) { + ASSERT_IS_WUI_THREAD (); + g_static_mutex_lock (&state_mutex); logged_in = new_logged_in; g_static_mutex_unlock (&state_mutex); @@ -280,6 +321,8 @@ set_logged_in (gboolean new_logged_in) static void set_busy (gboolean new_busy) { + ASSERT_IS_WUI_THREAD (); + g_static_mutex_lock (&state_mutex); busy = new_busy; g_static_mutex_unlock (&state_mutex); @@ -298,6 +341,8 @@ wui_thread_is_connected (void) { gboolean ret; + ASSERT_IS_MAIN_THREAD (); + g_static_mutex_lock (&state_mutex); ret = connected; g_static_mutex_unlock (&state_mutex); @@ -309,6 +354,8 @@ wui_thread_is_logged_in (void) { gboolean ret; + ASSERT_IS_MAIN_THREAD (); + g_static_mutex_lock (&state_mutex); ret = logged_in; g_static_mutex_unlock (&state_mutex); @@ -320,6 +367,8 @@ wui_thread_is_busy (void) { gboolean ret; + ASSERT_IS_MAIN_THREAD (); + g_static_mutex_lock (&state_mutex); ret = busy; g_static_mutex_unlock (&state_mutex); @@ -330,6 +379,8 @@ wui_thread_is_busy (void) static gboolean process_message (struct message *msg) { + ASSERT_IS_WUI_THREAD (); + switch (msg->type) { case QUIT: write_fn_discard_capture_buffer (); @@ -432,6 +483,8 @@ write_fn (void *ptr, size_t size, size_t nmemb, void *stream) int bytes = size * nmemb; int old_start; + ASSERT_IS_WUI_THREAD (); + if (write_fn_len >= 0) { /* We're capturing. */ old_start = write_fn_len; write_fn_len += bytes; @@ -446,6 +499,8 @@ write_fn (void *ptr, size_t size, size_t nmemb, void *stream) static void write_fn_start_capture (void) { + ASSERT_IS_WUI_THREAD (); + write_fn_discard_capture_buffer (); write_fn_buffer = NULL; write_fn_len = 0; @@ -457,6 +512,8 @@ write_fn_finish_capture (void) { char *ret = write_fn_buffer; + ASSERT_IS_WUI_THREAD (); + write_fn_buffer = NULL; write_fn_len = -1; return ret; @@ -466,6 +523,8 @@ write_fn_finish_capture (void) static void write_fn_discard_capture_buffer (void) { + ASSERT_IS_WUI_THREAD (); + g_free (write_fn_buffer); write_fn_buffer = NULL; write_fn_len = -1; @@ -475,6 +534,9 @@ static size_t header_fn (void *ptr, size_t size, size_t nmemb, void *stream) { int bytes = size * nmemb; + + ASSERT_IS_WUI_THREAD (); + return bytes; } @@ -484,6 +546,8 @@ do_curl_init (void) { DEBUG ("initializing libcurl"); + ASSERT_IS_WUI_THREAD (); + curl = curl_easy_init (); if (!curl) { /* This is probably quite bad, so abort. */ DEBUG ("curl_easy_init failed"); @@ -522,6 +586,7 @@ do_connect (void) char *error_str; DEBUG ("connecting to uri %s", uri); + ASSERT_IS_WUI_THREAD (); /* Set the URI for libcurl. */ CURL_CHECK_ERROR (curl_easy_setopt, (curl, CURLOPT_URL, uri)); @@ -561,6 +626,7 @@ do_login (void) long code = 0; DEBUG ("logging in with username %s, password *****", username); + ASSERT_IS_WUI_THREAD (); /* Generate the login URI from the base URI. */ len = strlen (uri) + 6 + 1; @@ -630,6 +696,7 @@ refresh_vm_list (void) char *xml; DEBUG ("refreshing list of VMs"); + ASSERT_IS_WUI_THREAD (); /* Generate the vms URI from the base URI. */ len = strlen (uri) + 4 + 1; @@ -749,6 +816,8 @@ wui_thread_has_valid_vmlist (void) { gboolean ret; + ASSERT_IS_MAIN_THREAD (); + g_static_mutex_lock (&vmlist_mutex); ret = vmlist_valid; g_static_mutex_unlock (&vmlist_mutex); @@ -772,6 +841,8 @@ wui_thread_get_vmlist (GSList **ret) { gboolean r; + ASSERT_IS_MAIN_THREAD (); + r = FALSE; *ret = NULL; -- 1.8.3.1