aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--libsylph/socket.c9
-rw-r--r--libsylph/utils.c11
-rw-r--r--src/inc.c1
-rw-r--r--src/logwindow.c78
-rw-r--r--src/logwindow.h9
-rw-r--r--src/main.c30
-rw-r--r--src/send_message.c1
-rw-r--r--src/statusbar.c2
9 files changed, 135 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index bb74f56e..f3a82307 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
}
diff --git a/src/inc.c b/src/inc.c
index 2a55fe2c..5dfbd8af 100644
--- a/src/inc.c
+++ b/src/inc.c
@@ -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__ */
diff --git a/src/main.c b/src/main.c
index 82937164..af686954 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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, ...)