From efb45db411d5f64e95cc2eba2501ff3f73239cb3 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Fri, 22 Feb 2008 10:49:55 +0000 Subject: ** Fix for bug #512776 2008-02-22 Milan Crha ** Fix for bug #512776 * Changes below prevents deadlock on start or send/receive. * mail-send-recv.c: (struct _refresh_folders_msg), (refresh_folders_exec), (refresh_folders_free), (receive_update_got_folderinfo): Do not look for active folders in main thread, rather do it in other thread and free folder info later. * mail-ops.h: (mail_get_folderinfo): * mail-ops.c: (struct _get_folderinfo_msg), (get_folderinfo_done), (get_folderinfo_free), (mail_get_folderinfo): * mail-folder-cache.h: (mail_note_store): * mail-folder-cache.c: (struct _update_data), (update_folders), (mail_note_store): * mail-component.c: (mc_add_store_done): The 'done' function returns if we can free folder info or not. svn path=/trunk/; revision=35071 --- mail/ChangeLog | 20 +++++++++++++++++++- mail/mail-component.c | 4 +++- mail/mail-folder-cache.c | 11 +++++++---- mail/mail-folder-cache.h | 5 +++-- mail/mail-ops.c | 11 +++++++---- mail/mail-ops.h | 2 +- mail/mail-send-recv.c | 49 ++++++++++++++++++++++++++++-------------------- 7 files changed, 69 insertions(+), 33 deletions(-) (limited to 'mail') diff --git a/mail/ChangeLog b/mail/ChangeLog index 1ce93c3513..0c543da306 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,5 +1,23 @@ +2008-02-22 Milan Crha + + ** Fix for bug #512776 + + * Changes below prevents deadlock on start or send/receive. + * mail-send-recv.c: (struct _refresh_folders_msg), + (refresh_folders_exec), (refresh_folders_free), + (receive_update_got_folderinfo): Do not look for active folders in + main thread, rather do it in other thread and free folder info later. + * mail-ops.h: (mail_get_folderinfo): + * mail-ops.c: (struct _get_folderinfo_msg), (get_folderinfo_done), + (get_folderinfo_free), (mail_get_folderinfo): + * mail-folder-cache.h: (mail_note_store): + * mail-folder-cache.c: (struct _update_data), (update_folders), + (mail_note_store): + * mail-component.c: (mc_add_store_done): + The 'done' function returns if we can free folder info or not. + 2008-02-22 Srinivasa Ragavan - + ** Fix for BNC #358697 * em-folder-browser.c: (emfb_set_folder): Make sure the default search diff --git a/mail/mail-component.c b/mail/mail-component.c index 879c346494..0e5e19a398 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -206,7 +206,7 @@ store_info_unref(struct _store_info *si) g_free(si); } -static void +static gboolean mc_add_store_done(CamelStore *store, CamelFolderInfo *info, void *data) { struct _store_info *si = data; @@ -223,6 +223,8 @@ mc_add_store_done(CamelStore *store, CamelFolderInfo *info, void *data) } store_info_unref(si); + + return TRUE; } /* Utility functions. */ diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index b88d8f79ac..417f115999 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -723,7 +723,7 @@ struct _update_data { int id; /* id for cancellation */ guint cancel:1; /* also tells us we're cancelled */ - void (*done)(CamelStore *store, CamelFolderInfo *info, void *data); + gboolean (*done)(CamelStore *store, CamelFolderInfo *info, void *data); void *data; }; @@ -782,11 +782,12 @@ mail_note_store_remove(CamelStore *store) UNLOCK(info_lock); } -static void +static gboolean update_folders(CamelStore *store, CamelFolderInfo *fi, void *data) { struct _update_data *ud = data; struct _store_info *si; + gboolean res = TRUE; d(printf("Got folderinfo for store %s\n", store->parent_object.provider->protocol)); @@ -803,8 +804,10 @@ update_folders(CamelStore *store, CamelFolderInfo *fi, void *data) UNLOCK(info_lock); if (ud->done) - ud->done(store, fi, ud->data); + res = ud->done (store, fi, ud->data); g_free(ud); + + return res; } @@ -906,7 +909,7 @@ store_online_cb (CamelStore *store, void *data) void mail_note_store(CamelStore *store, CamelOperation *op, - void (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data) + gboolean (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data) { struct _store_info *si; struct _update_data *ud; diff --git a/mail/mail-folder-cache.h b/mail/mail-folder-cache.h index 656d97135b..3c16e8c54e 100644 --- a/mail/mail-folder-cache.h +++ b/mail/mail-folder-cache.h @@ -29,10 +29,11 @@ /* Add a store whose folders should appear in the shell The folders are scanned from the store, and/or added at - runtime via the folder_created event */ + runtime via the folder_created event. + The 'done' function returns if we can free folder info. */ void mail_note_store (CamelStore *store, CamelOperation *op, - void (*done) (CamelStore *store, CamelFolderInfo *info, void *data), + gboolean (*done) (CamelStore *store, CamelFolderInfo *info, void *data), void *data); /* de-note a store */ diff --git a/mail/mail-ops.c b/mail/mail-ops.c index 894d4d8c2f..f11c2e0258 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -1042,8 +1042,9 @@ struct _get_folderinfo_msg { CamelStore *store; CamelFolderInfo *info; - void (*done)(CamelStore *store, CamelFolderInfo *info, void *data); + gboolean (*done)(CamelStore *store, CamelFolderInfo *info, void *data); void *data; + gboolean can_clear; /* whether we can clear folder info */ }; static gchar * @@ -1078,13 +1079,15 @@ get_folderinfo_done (struct _get_folderinfo_msg *m) } if (m->done) - m->done (m->store, m->info, m->data); + m->can_clear = m->done (m->store, m->info, m->data); + else + m->can_clear = TRUE; } static void get_folderinfo_free (struct _get_folderinfo_msg *m) { - if (m->info) + if (m->info && m->can_clear) camel_store_free_folder_info(m->store, m->info); camel_object_unref(m->store); } @@ -1098,7 +1101,7 @@ static MailMsgInfo get_folderinfo_info = { }; int -mail_get_folderinfo (CamelStore *store, CamelOperation *op, void (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data) +mail_get_folderinfo (CamelStore *store, CamelOperation *op, gboolean (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data) { struct _get_folderinfo_msg *m; int id; diff --git a/mail/mail-ops.h b/mail/mail-ops.h index e23e775645..8b532e896f 100644 --- a/mail/mail-ops.h +++ b/mail/mail-ops.h @@ -103,7 +103,7 @@ void mail_empty_trash (EAccount *account, /* get folder info asynchronously */ int mail_get_folderinfo (CamelStore *store, CamelOperation *op, - void (*done)(CamelStore *store, CamelFolderInfo *info, void *data), + gboolean (*done)(CamelStore *store, CamelFolderInfo *info, void *data), void *data); /* remove an existing folder */ diff --git a/mail/mail-send-recv.c b/mail/mail-send-recv.c index 5c4454d7cb..3b922c549b 100644 --- a/mail/mail-send-recv.c +++ b/mail/mail-send-recv.c @@ -778,12 +778,30 @@ receive_get_folder(CamelFilterDriver *d, const char *uri, void *data, CamelExcep /* ********************************************************************** */ +static void +get_folders (CamelStore *store, GPtrArray *folders, CamelFolderInfo *info) +{ + CamelException ex; + + camel_exception_init (&ex); + + while (info) { + if (camel_store_can_refresh_folder (store, info, &ex)) + g_ptr_array_add (folders, g_strdup (info->uri)); + camel_exception_clear (&ex); + + get_folders (store, folders, info->child); + info = info->next; + } +} + struct _refresh_folders_msg { MailMsg base; struct _send_info *info; GPtrArray *folders; CamelStore *store; + CamelFolderInfo *finfo; }; static gchar * @@ -799,6 +817,8 @@ refresh_folders_exec (struct _refresh_folders_msg *m) CamelFolder *folder; CamelException ex = CAMEL_EXCEPTION_INITIALISER; + get_folders (m->store, m->folders, m->finfo); + for (i=0;ifolders->len;i++) { folder = mail_tool_uri_to_folder(m->folders->pdata[i], 0, &ex); if (folder) { @@ -829,6 +849,8 @@ refresh_folders_free (struct _refresh_folders_msg *m) for (i=0;ifolders->len;i++) g_free(m->folders->pdata[i]); g_ptr_array_free(m->folders, TRUE); + + camel_store_free_folder_info (m->store, m->finfo); camel_object_unref(m->store); } @@ -840,24 +862,7 @@ static MailMsgInfo refresh_folders_info = { (MailMsgFreeFunc) refresh_folders_free }; -static void -get_folders (CamelStore *store, GPtrArray *folders, CamelFolderInfo *info) -{ - CamelException ex; - - camel_exception_init (&ex); - - while (info) { - if (camel_store_can_refresh_folder (store, info, &ex)) - g_ptr_array_add (folders, g_strdup (info->uri)); - camel_exception_clear (&ex); - - get_folders (store, folders, info->child); - info = info->next; - } -} - -static void +static gboolean receive_update_got_folderinfo(CamelStore *store, CamelFolderInfo *info, void *data) { if (info) { @@ -865,18 +870,22 @@ receive_update_got_folderinfo(CamelStore *store, CamelFolderInfo *info, void *da struct _refresh_folders_msg *m; struct _send_info *sinfo = data; - get_folders(store, folders, info); - m = mail_msg_new(&refresh_folders_info); m->store = store; camel_object_ref(store); m->folders = folders; m->info = sinfo; + m->finfo = info; mail_msg_unordered_push (m); + + /* do not free folder info, we will free it later */ + return FALSE; } else { receive_done ("", data); } + + return TRUE; } static void -- cgit v1.2.3