diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | libsylph/socket.c | 9 | ||||
-rw-r--r-- | libsylph/utils.c | 11 | ||||
-rw-r--r-- | src/inc.c | 1 | ||||
-rw-r--r-- | src/logwindow.c | 78 | ||||
-rw-r--r-- | src/logwindow.h | 9 | ||||
-rw-r--r-- | src/main.c | 30 | ||||
-rw-r--r-- | src/send_message.c | 1 | ||||
-rw-r--r-- | src/statusbar.c | 2 |
9 files changed, 135 insertions, 17 deletions
@@ -1,3 +1,14 @@ +2009-09-29 + + * src/logwindow.[ch]: made LogWindow thread-safe. + * libsylph/utils.c + libsylph/socket.c + src/inc.c + src/statusbar.c + src/send_message.c + src/main.c: made gdk_threads_enter() / gdk_threads_leave() + reentrant. + 2009-09-25 * libsylph/utils.[ch] diff --git a/libsylph/socket.c b/libsylph/socket.c index 5b2ea960..1dc9448d 100644 --- a/libsylph/socket.c +++ b/libsylph/socket.c @@ -1329,11 +1329,10 @@ static gpointer sock_connect_async_func(gpointer data) { SockConnectData *conn_data = (SockConnectData *)data; - g_print("sock_connect_async_func: connect\n"); conn_data->sock = sock_connect(conn_data->hostname, conn_data->port); conn_data->flag = 1; - g_print("sock_connect_async_func: connected\n"); + debug_print("sock_connect_async_func: connected\n"); g_main_context_wakeup(NULL); return GINT_TO_POINTER(0); @@ -1380,13 +1379,13 @@ gint sock_connect_async_wait(gint id, SockInfo **sock) return -1; } - g_print("sock_connect_async_wait: waiting thread\n"); + debug_print("sock_connect_async_wait: waiting thread\n"); while (conn_data->flag == 0) event_loop_iterate(); - g_print("sock_connect_async_wait: flagged\n"); + debug_print("sock_connect_async_wait: flagged\n"); g_thread_join(conn_data->thread); - g_print("sock_connect_async_wait: thread exited\n"); + debug_print("sock_connect_async_wait: thread exited\n"); *sock = conn_data->sock; diff --git a/libsylph/utils.c b/libsylph/utils.c index c0664488..fb9f30be 100644 --- a/libsylph/utils.c +++ b/libsylph/utils.c @@ -3875,16 +3875,15 @@ static gpointer execute_command_line_async_func(gpointer data) CmdData *cmd_data = (CmdData *)data; gchar **argv; - g_print("execute_command_line_async_func\n"); argv = strsplit_with_quote(cmd_data->cmdline, " ", 0); cmd_data->status = execute_sync(argv); g_strfreev(argv); - g_print("execute_command_line_async_func: exec done.\n"); + debug_print("execute_command_line_async_func: exec done: %s\n", + cmd_data->cmdline); cmd_data->flag = 1; g_main_context_wakeup(NULL); - g_print("execute_command_line_async_func: exiting\n"); return GINT_TO_POINTER(0); } @@ -3909,13 +3908,13 @@ gint execute_command_line_async_wait(const gchar *cmdline) if (!thread) return -1; - g_print("execute_command_line_async_wait: waiting thread\n"); + debug_print("execute_command_line_async_wait: waiting thread\n"); while (data.flag == 0) event_loop_iterate(); - g_print("execute_command_line_async_wait: flagged\n"); + debug_print("execute_command_line_async_wait: flagged\n"); g_thread_join(thread); - g_print("execute_command_line_async_wait: thread exited\n"); + debug_print("execute_command_line_async_wait: thread exited\n"); return data.status; } @@ -865,6 +865,7 @@ static IncState inc_pop3_session_do(IncSession *session) session->inc_state != INC_CANCEL) { gtk_main_iteration(); } + log_window_flush(); if (session->inc_state == INC_SUCCESS) { switch (pop3_session->error_val) { diff --git a/src/logwindow.c b/src/logwindow.c index 017bb37b..beab32a8 100644 --- a/src/logwindow.c +++ b/src/logwindow.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto + * Copyright (C) 1999-2009 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +41,10 @@ static LogWindow *logwindow; +#if USE_THREADS +static GThread *main_thread; +#endif + static void log_window_print_func (const gchar *str); static void log_window_message_func (const gchar *str); static void log_window_warning_func (const gchar *str); @@ -99,6 +103,13 @@ LogWindow *log_window_create(void) logwin->text = text; logwin->lines = 1; +#if USE_THREADS + logwin->aqueue = g_async_queue_new(); + + main_thread = g_thread_self(); + debug_print("main_thread = %p\n", main_thread); +#endif + logwindow = logwin; return logwin; @@ -160,7 +171,7 @@ void log_window_show(LogWindow *logwin) gtk_window_present(GTK_WINDOW(logwin->window)); } -void log_window_append(const gchar *str, LogType type) +static void log_window_append_real(const gchar *str, LogType type) { GtkTextView *text; GtkTextBuffer *buffer; @@ -172,6 +183,14 @@ void log_window_append(const gchar *str, LogType type) g_return_if_fail(logwindow != NULL); +#if USE_THREADS + if (g_thread_self() != main_thread) { + return; + } +#endif + + gdk_threads_enter(); + text = GTK_TEXT_VIEW(logwindow->text); buffer = gtk_text_view_get_buffer(text); @@ -233,6 +252,61 @@ void log_window_append(const gchar *str, LogType type) } logwindow->lines++; + + gdk_threads_leave(); +} + +void log_window_append(const gchar *str, LogType type) +{ +#if USE_THREADS + if (g_thread_self() != main_thread) { + fprintf(stderr, "log_window_append called from non-main thread (%p)\n", g_thread_self()); + log_window_append_queue(str, type); + return; + } + + log_window_flush(); +#endif + log_window_append_real(str, type); +} + +typedef struct _LogData +{ + gchar *str; + LogType type; +} LogData; + +void log_window_append_queue(const gchar *str, LogType type) +{ +#if USE_THREADS + LogData *logdata; + + logdata = g_new(LogData, 1); + logdata->str = g_strdup(str); + logdata->type = type; + + g_print("append_queue: (%d) %s\n", type, str); + g_async_queue_push(logwindow->aqueue, logdata); +#endif +} + +void log_window_flush(void) +{ +#if USE_THREADS + LogData *logdata; + + if (g_thread_self() != main_thread) { + fprintf(stderr, "log_window_flush called from non-main thread (%p)\n", g_thread_self()); + return; + } + + while ((logdata = g_async_queue_try_pop(logwindow->aqueue))) { + g_print("flush_queue: (%d) %s\n", logdata->type, logdata->str); + log_window_append_real(logdata->str, logdata->type); + g_free(logdata->str); + g_free(logdata); + } +#endif } static void log_window_print_func(const gchar *str) diff --git a/src/logwindow.h b/src/logwindow.h index 97a9159f..7e4a1d47 100644 --- a/src/logwindow.h +++ b/src/logwindow.h @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2003 Hiroyuki Yamamoto + * Copyright (C) 1999-2009 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,6 +44,10 @@ struct _LogWindow GdkColor error_color; gint lines; + +#if USE_THREADS + GAsyncQueue *aqueue; +#endif }; LogWindow *log_window_create(void); @@ -51,5 +55,8 @@ void log_window_init(LogWindow *logwin); void log_window_show(LogWindow *logwin); void log_window_append(const gchar *str, LogType type); +void log_window_append_queue(const gchar *str, LogType type); + +void log_window_flush(void); #endif /* __LOGWINDOW_H__ */ @@ -580,11 +580,32 @@ static gint get_queued_message_num(void) } #if USE_THREADS +/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */ +static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT; + +static void thread_enter_func(void) +{ + g_static_rec_mutex_lock(&syl_mutex); +#if 0 + syl_mutex_lock_count++; + if (syl_mutex_lock_count > 1) + g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count); +#endif +} + +static void thread_leave_func(void) +{ +#if 0 + syl_mutex_lock_count--; + if (syl_mutex_lock_count > 0) + g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count); +#endif + g_static_rec_mutex_unlock(&syl_mutex); +} + static void event_loop_iteration_func(void) { - //g_print("event_loop_iteration_func start\n"); gtk_main_iteration(); - //g_print("event_loop_iteration_func end\n"); } #endif @@ -595,8 +616,11 @@ static void app_init(void) g_thread_init(NULL); if (!g_thread_supported()) g_error("g_thread is not supported by glib."); - else + else { + gdk_threads_set_lock_functions(thread_enter_func, + thread_leave_func); gdk_threads_init(); + } #endif syl_init(); diff --git a/src/send_message.c b/src/send_message.c index c44232d4..e2527292 100644 --- a/src/send_message.c +++ b/src/send_message.c @@ -747,6 +747,7 @@ static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp) while (session_is_connected(session) && dialog->cancelled == FALSE) gtk_main_iteration(); + log_window_flush(); if (SMTP_SESSION(session)->error_val == SM_AUTHFAIL) { if (ac_prefs->smtp_userid && ac_prefs->tmp_smtp_pass) { diff --git a/src/statusbar.c b/src/statusbar.c index c4f7a6d4..2bd7ff8d 100644 --- a/src/statusbar.c +++ b/src/statusbar.c @@ -67,8 +67,10 @@ void statusbar_puts_all(const gchar *str) { GList *cur; + gdk_threads_enter(); for (cur = statusbar_list; cur != NULL; cur = cur->next) statusbar_puts(GTK_STATUSBAR(cur->data), str); + gdk_threads_leave(); } void statusbar_print(GtkStatusbar *statusbar, const gchar *format, ...) |