From ba5b1b6be7d3beed85c1f6b51d5808f9a7d72b5f Mon Sep 17 00:00:00 2001 From: 5 Date: Tue, 25 Sep 2001 22:18:52 +0000 Subject: Deal with destroy vs finalise semantics. Only destroy widgets here. 2001-09-25 * folder-browser.c (folder_browser_destroy): Deal with destroy vs finalise semantics. Only destroy widgets here. (folder_browser_finalise): object finalise function, actually unref/free all other objects here. (folder_browser_class_init): Init the finalise hook. (got_folder): Check if message_list == NULL -> we've been destroyed before the thread got a chance to finish loading the folder. (folder_browser_is_drafts): Dont use a g_return_if_fail to return in what could be a valid state of the object. (folder_browser_is_sent): Likewise. (folder_browser_copy): Do nothing if message_list == NULL. * main.c (main): call mail_msg_cleanup() before leaving threads. * component-factory.c (owner_unset_cb): Wait for all outstanding operations to finish before setting up to quit. (idle_quit): Wait for all outstanding ops to finish before cleanup. (unref_standard_folders): NULL out the standard folder before unreffing it. * mail-mt.c (mail_msg_wait_all): New function to wait for all outstanding thread operations. (mail_msg_cleanup): Destroy the io channels before we're finished. Also wait for all outstanding threads first. Made public. (mail_msg_init): Dont call mail_msg_cleanup atexit automatically. svn path=/trunk/; revision=13129 --- mail/ChangeLog | 32 +++++++++++++++++++++++ mail/component-factory.c | 12 +++++++-- mail/folder-browser.c | 67 ++++++++++++++++++++++++++++++++++++------------ mail/mail-mt.c | 35 +++++++++++++++++++++---- mail/mail-mt.h | 1 + mail/main.c | 3 +++ 6 files changed, 127 insertions(+), 23 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index 0a9670b38f..8f869194bb 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,35 @@ +2001-09-25 + + * folder-browser.c (folder_browser_destroy): Deal with destroy vs + finalise semantics. Only destroy widgets here. + (folder_browser_finalise): object finalise function, actually + unref/free all other objects here. + (folder_browser_class_init): Init the finalise hook. + (got_folder): Check if message_list == NULL -> we've been + destroyed before the thread got a chance to finish loading the + folder. + (folder_browser_is_drafts): Dont use a g_return_if_fail to return + in what could be a valid state of the object. + (folder_browser_is_sent): Likewise. + (folder_browser_copy): Do nothing if message_list == NULL. + + * main.c (main): call mail_msg_cleanup() before leaving threads. + + * component-factory.c (owner_unset_cb): Wait for all outstanding + operations to finish before setting up to quit. + (idle_quit): Wait for all outstanding ops to finish before + cleanup. + (unref_standard_folders): NULL out the standard folder before + unreffing it. + + * mail-mt.c (mail_msg_wait_all): New function to wait for all + outstanding thread operations. + (mail_msg_cleanup): Destroy the io channels before we're + finished. Also wait for all outstanding threads first. Made + public. + (mail_msg_init): Dont call mail_msg_cleanup atexit automatically. + + 2001-09-25 Jeffrey Stedfast * mail-format.c (get_data_wrapper_text): If the data wrapper diff --git a/mail/component-factory.c b/mail/component-factory.c index cddf142891..5019702e3a 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -603,8 +603,12 @@ unref_standard_folders (void) int i; for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++) { - if (standard_folders[i].folder) - camel_object_unref (CAMEL_OBJECT (*standard_folders[i].folder)); + if (standard_folders[i].folder) { + CamelFolder *folder = *standard_folders[i].folder; + + *standard_folders[i].folder = NULL; + camel_object_unref (CAMEL_OBJECT (folder)); + } } } @@ -712,6 +716,8 @@ free_storage (gpointer service, gpointer storage, gpointer data) static gboolean idle_quit (gpointer user_data) { + mail_msg_wait_all(); + if (e_list_length (folder_browser_factory_get_control_list ())) return TRUE; @@ -730,6 +736,8 @@ owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data) if (mail_config_get_empty_trash_on_exit ()) empty_trash (NULL, NULL, NULL); + + mail_msg_wait_all(); unref_standard_folders (); mail_importer_uninit (); diff --git a/mail/folder-browser.c b/mail/folder-browser.c index f577d46e88..492a17b900 100644 --- a/mail/folder-browser.c +++ b/mail/folder-browser.c @@ -109,13 +109,13 @@ enum { static guint folder_browser_signals [LAST_SIGNAL] = {0, }; static void -folder_browser_destroy (GtkObject *object) +folder_browser_finalise (GtkObject *object) { FolderBrowser *folder_browser; CORBA_Environment ev; - - folder_browser = FOLDER_BROWSER (object); - + + folder_browser = FOLDER_BROWSER(object); + CORBA_exception_init (&ev); if (folder_browser->search_full) @@ -124,17 +124,22 @@ folder_browser_destroy (GtkObject *object) if (folder_browser->sensitize_timeout_id) g_source_remove (folder_browser->sensitize_timeout_id); - if (folder_browser->shell != CORBA_OBJECT_NIL) + if (folder_browser->shell != CORBA_OBJECT_NIL) { CORBA_Object_release (folder_browser->shell, &ev); + folder_browser->shell = CORBA_OBJECT_NIL; + } - if (folder_browser->shell_view != CORBA_OBJECT_NIL) + if (folder_browser->shell_view != CORBA_OBJECT_NIL) { CORBA_Object_release(folder_browser->shell_view, &ev); + folder_browser->shell_view = CORBA_OBJECT_NIL; + } if (folder_browser->uicomp) bonobo_object_unref (BONOBO_OBJECT (folder_browser->uicomp)); g_free (folder_browser->uri); - + folder_browser->uri = NULL; + if (folder_browser->folder) { camel_object_unhook_event(CAMEL_OBJECT(folder_browser->folder), "folder_changed", folder_changed, folder_browser); @@ -142,14 +147,9 @@ folder_browser_destroy (GtkObject *object) folder_changed, folder_browser); mail_sync_folder (folder_browser->folder, NULL, NULL); camel_object_unref (CAMEL_OBJECT (folder_browser->folder)); + folder_browser->folder = NULL; } - if (folder_browser->message_list) - gtk_widget_destroy (GTK_WIDGET (folder_browser->message_list)); - - if (folder_browser->mail_display) - gtk_widget_destroy (GTK_WIDGET (folder_browser->mail_display)); - CORBA_exception_free (&ev); if (folder_browser->view_collection) { @@ -163,9 +163,31 @@ folder_browser_destroy (GtkObject *object) } gtk_object_unref (GTK_OBJECT (folder_browser->invisible)); + folder_browser->invisible = NULL; + if (folder_browser->clipboard_selection) g_byte_array_free (folder_browser->clipboard_selection, TRUE); + + folder_browser_parent_class->finalize(object); +} + +static void +folder_browser_destroy (GtkObject *object) +{ + FolderBrowser *folder_browser; + + folder_browser = FOLDER_BROWSER (object); + + if (folder_browser->message_list) { + gtk_widget_destroy (GTK_WIDGET (folder_browser->message_list)); + folder_browser->message_list = NULL; + } + if (folder_browser->mail_display) { + gtk_widget_destroy (GTK_WIDGET (folder_browser->mail_display)); + folder_browser->mail_display = NULL; + } + folder_browser_parent_class->destroy (object); } @@ -173,6 +195,7 @@ static void folder_browser_class_init (GtkObjectClass *object_class) { object_class->destroy = folder_browser_destroy; + object_class->finalize = folder_browser_finalise; folder_browser_parent_class = gtk_type_class (PARENT_TYPE); @@ -630,6 +653,9 @@ folder_browser_copy (GtkWidget *menuitem, FolderBrowser *fb) gboolean cut; int i; + if (fb->message_list == NULL) + return; + cut = menuitem == NULL; if (!GTK_WIDGET_HAS_FOCUS (fb->message_list)) { @@ -748,6 +774,9 @@ got_folder(char *uri, CamelFolder *folder, void *data) FolderBrowser *fb = data; d(printf ("got folder '%s' = %p\n", uri, folder)); + + if (fb->message_list == NULL) + goto done; fb->folder = folder; if (folder == NULL) @@ -824,7 +853,10 @@ folder_browser_is_drafts (FolderBrowser *fb) const GSList *accounts; MailConfigAccount *account; - g_return_val_if_fail (IS_FOLDER_BROWSER (fb) && fb->uri, FALSE); + g_return_val_if_fail (IS_FOLDER_BROWSER (fb), FALSE); + + if (fb->uri == NULL) + return FALSE; if (fb->folder == drafts_folder) return TRUE; @@ -854,8 +886,11 @@ folder_browser_is_sent (FolderBrowser *fb) const GSList *accounts; MailConfigAccount *account; - g_return_val_if_fail (IS_FOLDER_BROWSER (fb) && fb->uri, FALSE); - + g_return_val_if_fail (IS_FOLDER_BROWSER (fb), FALSE); + + if (fb->uri == NULL) + return FALSE; + if (fb->folder == sent_folder) return TRUE; diff --git a/mail/mail-mt.c b/mail/mail-mt.c index 69646e44fd..2ce8f6cab4 100644 --- a/mail/mail-mt.c +++ b/mail/mail-mt.c @@ -260,6 +260,28 @@ void mail_msg_wait(unsigned int msgid) } } +void mail_msg_wait_all(void) +{ + struct _mail_msg *m; + int ismain = pthread_self() == mail_gui_thread; + + if (ismain) { + MAIL_MT_LOCK(mail_msg_lock); + while (g_hash_table_size(mail_msg_active) > 0) { + MAIL_MT_UNLOCK(mail_msg_lock); + gtk_main_iteration(); + MAIL_MT_LOCK(mail_msg_lock); + } + MAIL_MT_UNLOCK(mail_msg_lock); + } else { + MAIL_MT_LOCK(mail_msg_lock); + while (g_hash_table_size(mail_msg_active) > 0) { + pthread_cond_wait(&mail_msg_cond, &mail_msg_lock); + } + MAIL_MT_UNLOCK(mail_msg_lock); + } +} + EMsgPort *mail_gui_port; static GIOChannel *mail_gui_channel; EMsgPort *mail_gui_reply_port; @@ -366,16 +388,19 @@ mail_msg_received(EThread *e, EMsg *msg, void *data) } } -static void mail_msg_cleanup(void) +void mail_msg_cleanup(void) { + mail_msg_wait_all(); + e_thread_destroy(mail_thread_queued_slow); e_thread_destroy(mail_thread_queued); e_thread_destroy(mail_thread_new); + g_io_channel_unref(mail_gui_channel); + g_io_channel_unref(mail_gui_reply_channel); + e_msgport_destroy(mail_gui_port); e_msgport_destroy(mail_gui_reply_port); - - /* FIXME: channels too, etc */ } void mail_msg_init(void) @@ -406,8 +431,6 @@ void mail_msg_init(void) mail_msg_active = g_hash_table_new(NULL, NULL); mail_gui_thread = pthread_self(); - - atexit(mail_msg_cleanup); } /* ********************************************************************** */ @@ -450,6 +473,8 @@ pass_got (char *string, void *data) service = mca->transport; } + mail_config_service_set_save_passwd (service, remember); + if (mca) { mail_config_service_set_save_passwd (service, remember); diff --git a/mail/mail-mt.h b/mail/mail-mt.h index 8f90c3b0c7..c8717d33ac 100644 --- a/mail/mail-mt.h +++ b/mail/mail-mt.h @@ -56,6 +56,7 @@ void mail_msg_free(void *msg); void mail_msg_check_error(void *msg); void mail_msg_cancel(unsigned int msgid); void mail_msg_wait(unsigned int msgid); +void mail_msg_wait_all(void); /* request a string/password */ char *mail_get_password (CamelService *service, const char *prompt, diff --git a/mail/main.c b/mail/main.c index 41a9482167..dc2042f19b 100644 --- a/mail/main.c +++ b/mail/main.c @@ -139,6 +139,9 @@ main (int argc, char *argv []) GDK_THREADS_ENTER (); bonobo_main (); + + mail_msg_cleanup(); + GDK_THREADS_LEAVE (); mail_config_write_on_exit (); -- cgit