2007-07-03 Murray Cumming <murrayc@murrayc.com>
authorMurray Cumming <murrayc@murrayc.com>
Tue, 3 Jul 2007 11:39:52 +0000 (11:39 +0000)
committerMurray Cumming <murrayc@murrayc.com>
Tue, 3 Jul 2007 11:39:52 +0000 (11:39 +0000)
* src/modest-tny-account.c:
        (modest_tny_account_get_special_folder): (util_on_idle),
        Handle the GError so we can see when tny_folder_store_get_folders()
        fails, as it currently does while something else is connecting.

        Added util_run_in_main_thread_and_wait()
        which uses an idlen handler and mainloop to ensure that the function
        is called in the main thread.
        (on_connection_status_changed): Use util_run_in_main_thread_and_wait()
        to make sure that we call attempt the connection in the mainloop only,
        which might solve some hangs.

pmo-trunk-r2548

ChangeLog2
src/modest-tny-account.c

index badf363..a24ca67 100644 (file)
@@ -1,5 +1,19 @@
 2007-07-03  Murray Cumming <murrayc@murrayc.com>
 
 2007-07-03  Murray Cumming <murrayc@murrayc.com>
 
+       * src/modest-tny-account.c:
+       (modest_tny_account_get_special_folder): (util_on_idle),
+       Handle the GError so we can see when tny_folder_store_get_folders() 
+       fails, as it currently does while something else is connecting.
+       
+       Added util_run_in_main_thread_and_wait() 
+       which uses an idlen handler and mainloop to ensure that the function 
+       is called in the main thread.
+       (on_connection_status_changed): Use util_run_in_main_thread_and_wait() 
+       to make sure that we call attempt the connection in the mainloop only, 
+       which might solve some hangs.
+       
+2007-07-03  Murray Cumming <murrayc@murrayc.com>
+
        (modest_tny_account_store_get_tny_account_by): Do not allow accounts to 
        be found by their display name. This is never useful.
        * src/modest-tny-account-store.c: (on_account_removed): Find the account 
        (modest_tny_account_store_get_tny_account_by): Do not allow accounts to 
        be found by their display name. This is never useful.
        * src/modest-tny-account-store.c: (on_account_removed): Find the account 
index 8b750e3..7ca1808 100644 (file)
@@ -106,8 +106,13 @@ modest_tny_account_get_special_folder (TnyAccount *account,
        /* There is no need to do this _async, as these are local folders. */
        /* TODO: However, this seems to fail sometimes when the network is busy, 
         * returning an empty list. murrayc. */ 
        /* There is no need to do this _async, as these are local folders. */
        /* TODO: However, this seems to fail sometimes when the network is busy, 
         * returning an empty list. murrayc. */ 
+       GError *error = NULL;
        tny_folder_store_get_folders (TNY_FOLDER_STORE (local_account),
        tny_folder_store_get_folders (TNY_FOLDER_STORE (local_account),
-                                     folders, NULL, NULL);
+                                     folders, NULL, &error);
+       if (error) {
+               g_warning ("%s: tny_folder_store_get_folders() failed:\n  error=%s\n", 
+                       __FUNCTION__, error->message);
+       }
                                      
        if (tny_list_get_length (folders) == 0) {
                gchar* url_string = tny_account_get_url_string (local_account);
                                      
        if (tny_list_get_length (folders) == 0) {
                gchar* url_string = tny_account_get_url_string (local_account);
@@ -143,6 +148,54 @@ modest_tny_account_get_special_folder (TnyAccount *account,
        return special_folder;
 }
 
        return special_folder;
 }
 
+typedef struct
+{
+       GSourceFunc func;
+       GMainLoop* loop;
+} UtilIdleData;
+
+static gboolean util_on_idle(gpointer user_data)
+{
+       /* We are now in the main thread, 
+        * so we can call the function:
+        */
+       UtilIdleData *idle_data = (UtilIdleData*)user_data;
+       if (idle_data && idle_data->func)
+               (*(idle_data->func))(NULL);
+
+       /* Stop the main loop so that the caller can continue: */
+       if (idle_data->loop)
+               g_main_loop_quit (idle_data->loop);
+
+       return FALSE; /* Stop calling this callback. */
+}
+
+static void
+util_run_in_main_thread_and_wait(GSourceFunc function)
+{
+       UtilIdleData *data = g_slice_new0 (UtilIdleData);
+       data->func = function;
+       data->loop = g_main_loop_new (NULL, FALSE /* not running */);
+       
+       /* Cause the function to be run in an idle-handler, which is always 
+        * in the main thread:
+        */
+       g_idle_add (util_on_idle, data);
+
+       /* This main loop will run until the idle handler has stopped it: */
+       g_main_loop_run (data->loop);
+       g_main_loop_unref (data->loop);
+
+       g_slice_free (UtilIdleData, data);
+}
+
+static gboolean 
+connect_and_wait(gpointer user_data)
+{
+       modest_platform_connect_and_wait(NULL);
+       return TRUE; /* Ignored */
+}
+
 static void
 on_connection_status_changed (TnyAccount *account, TnyConnectionStatus status, gpointer user_data)
 {
 static void
 on_connection_status_changed (TnyAccount *account, TnyConnectionStatus status, gpointer user_data)
 {
@@ -153,8 +206,12 @@ on_connection_status_changed (TnyAccount *account, TnyConnectionStatus status, g
                 * but the accounts are set as offline, because our TnyDevice is offline,
                 * because libconic says we are offline.
                 * So ask the user to go online:
                 * but the accounts are set as offline, because our TnyDevice is offline,
                 * because libconic says we are offline.
                 * So ask the user to go online:
+                *
+                * We make sure that this UI is shown in the main thread, to avoid races,
+                * because tinymail does not guarantee that this signal handler will be called 
+                * in the main thread.
                 */
                 */
-               modest_platform_connect_and_wait(NULL); 
+               util_run_in_main_thread_and_wait (&connect_and_wait);
        } else if (status == TNY_CONNECTION_STATUS_CONNECTED_BROKEN) {
                printf ("DEBUG: %s: Connection broken. Forcing TnyDevice offline.\n", 
                        __FUNCTION__);
        } else if (status == TNY_CONNECTION_STATUS_CONNECTED_BROKEN) {
                printf ("DEBUG: %s: Connection broken. Forcing TnyDevice offline.\n", 
                        __FUNCTION__);