2006-03-15 [colin] 2.0.0cvs140
authorColin Leroy <colin@colino.net>
Wed, 15 Mar 2006 18:05:53 +0000 (18:05 +0000)
committerColin Leroy <colin@colino.net>
Wed, 15 Mar 2006 18:05:53 +0000 (18:05 +0000)
* src/gtk/quicksearch.c
Fix a bitchy race we didn't think about when we
added quicksearch cancellation:
If the search is not on cached fields, for example
body_part matchcase "stuff"
the matcher code has to get the whole message. If
we're on IMAP, that can be slow, and in order to
be non-blocking, the IMAP code idle loop processes
gtk events too. So it is possible to cancel a
quicksearch while the matcher is getting the mail's
body. After matcher got its body, it will start to
iterate over the matcher list that the Quicksearch's
clear_search_cb() just freed via prepare_matcher().
SIGSEGV ensues.
The fix consists of guarding the matcherlist_match()
call with a boolean 'matching'. If we reset the
quicksearch while matching is TRUE, we don't free
the matcherlist anymore like we did, but we set
another new flag, deferred_free, to TRUE. Then,
in quicksearch_match(), just after returning from
matcherlist_match() and unsetting the matching flag,
we check the deferred_free flag and do the
prepare_matcher() (which does the matcherlist_free)
for real, so we free the matcherlist once it's not
used anymore.
As all of this runs via the glib main loop, we
luckily don't need a mutex.
* src/summaryview.c
Also, show progress while searching.

ChangeLog
PATCHSETS
configure.ac
src/gtk/quicksearch.c
src/summaryview.c

index b2bcfe92324becd8c02465bdd0bfb6efe4afb26f..71ace855a2b6d2ad384d41006df0d4e6e82cfc2a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2006-03-15 [colin]     2.0.0cvs140
+
+       * src/gtk/quicksearch.c
+               Fix a bitchy race we didn't think about when we
+               added quicksearch cancellation:
+               If the search is not on cached fields, for example
+               body_part matchcase "stuff"
+               the matcher code has to get the whole message. If
+               we're on IMAP, that can be slow, and in order to
+               be non-blocking, the IMAP code idle loop processes
+               gtk events too. So it is possible to cancel a
+               quicksearch while the matcher is getting the mail's
+               body. After matcher got its body, it will start to
+               iterate over the matcher list that the Quicksearch's
+               clear_search_cb() just freed via prepare_matcher().
+               SIGSEGV ensues.
+               The fix consists of guarding the matcherlist_match()
+               call with a boolean 'matching'. If we reset the
+               quicksearch while matching is TRUE, we don't free
+               the matcherlist anymore like we did, but we set
+               another new flag, deferred_free, to TRUE. Then,
+               in quicksearch_match(), just after returning from
+               matcherlist_match() and unsetting the matching flag,
+               we check the deferred_free flag and do the
+               prepare_matcher() (which does the matcherlist_free)
+               for real, so we free the matcherlist once it's not
+               used anymore.
+               As all of this runs via the glib main loop, we
+               luckily don't need a mutex.
+       * src/summaryview.c
+               Also, show progress while searching.
+
+
 2006-03-14 [colin]     2.0.0cvs139
 
        * src/alertpanel.c
index 661137f5fbd7c71928ec9b21ba6ea8ac679cacf2..96e115b157cd8db8b927cec94b389f723ce9af24 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.115.2.76 -r 1.115.2.77 src/main.c;  ) > 2.0.0cvs137.patchset
 ( cvs diff -u -r 1.5.2.20 -r 1.5.2.21 src/prefs_spelling.c;  ) > 2.0.0cvs138.patchset
 ( cvs diff -u -r 1.17.2.21 -r 1.17.2.22 src/alertpanel.c;  ) > 2.0.0cvs139.patchset
+( cvs diff -u -r 1.1.2.34 -r 1.1.2.35 src/gtk/quicksearch.c;  cvs diff -u -r 1.395.2.181 -r 1.395.2.182 src/summaryview.c;  ) > 2.0.0cvs140.patchset
index 07ace455d6197c5ff4422924fb53227b6425dba0..9a0d1fcaf86d219adfbf80e30185fadbd219aa37 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=0
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=139
+EXTRA_VERSION=140
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 39ba4585010e593deb24a443a2ebbc52be9c0acf..71be2e480502f01d66beb25c40d821437c9e5531 100644 (file)
@@ -38,6 +38,8 @@
 #include "folderview.h"
 #include "folder.h"
 #include "prefs_matcher.h"
+#include "sylpheed.h"
+#include "statusbar.h"
 
 struct _QuickSearch
 {
@@ -57,6 +59,8 @@ struct _QuickSearch
        gpointer                         callback_data;
        gboolean                         running;
        gboolean                         has_focus;
+       gboolean                         matching;
+       gboolean                         deferred_free;
        FolderItem                      *root_folder_item;
 };
 
@@ -68,13 +72,21 @@ static void prepare_matcher(QuickSearch *quicksearch)
 {
        const gchar *search_string = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(quicksearch->search_string_entry)->entry));
 
+       if (search_string == NULL || search_string[0] == '\0') {
+               quicksearch_set_active(quicksearch, FALSE);
+       }
+
        if (quicksearch->matcher_list != NULL) {
+               if (quicksearch->matching) {
+                       quicksearch->deferred_free = TRUE;
+                       return;
+               }
+               quicksearch->deferred_free = FALSE;
                matcherlist_free(quicksearch->matcher_list);
                quicksearch->matcher_list = NULL;
        }
 
        if (search_string == NULL || search_string[0] == '\0') {
-               quicksearch_set_active(quicksearch, FALSE);
                return;
        }
 
@@ -292,7 +304,10 @@ static void search_description_cb(GtkWidget *widget)
 static gboolean clear_search_cb(GtkMenuItem *widget, gpointer data)
 {
        QuickSearch *quicksearch = (QuickSearch *)data;
-       
+
+       if (!quicksearch->active)
+               return TRUE;
+
        quicksearch_set(quicksearch, prefs_common.summary_quicksearch_type, "");
        
        return TRUE;
@@ -582,6 +597,7 @@ void quicksearch_set_execute_callback(QuickSearch *quicksearch,
 gboolean quicksearch_match(QuickSearch *quicksearch, MsgInfo *msginfo)
 {
        gchar *searched_header = NULL;
+       gboolean result = FALSE;
 
        if (!quicksearch->active)
                return TRUE;
@@ -602,16 +618,21 @@ gboolean quicksearch_match(QuickSearch *quicksearch, MsgInfo *msginfo)
                debug_print("unknown search type (%d)\n", prefs_common.summary_quicksearch_type);
                break;
        }
-
+       quicksearch->matching = TRUE;
        if (prefs_common.summary_quicksearch_type != QUICK_SEARCH_EXTENDED && 
            quicksearch->search_string &&
             searched_header && strcasestr(searched_header, quicksearch->search_string) != NULL)
-               return TRUE;
+               result = TRUE;
        else if ((quicksearch->matcher_list != NULL) && 
-                matcherlist_match(quicksearch->matcher_list, msginfo))
-               return TRUE;
+                matcherlist_match(quicksearch->matcher_list, msginfo)) 
+               result = TRUE;
 
-       return FALSE;
+       quicksearch->matching = FALSE;
+       if (quicksearch->deferred_free) {
+               prepare_matcher(quicksearch);
+       }
+
+       return result;
 }
 
 /* allow Mutt-like patterns in quick search */
@@ -836,9 +857,12 @@ static gboolean quicksearch_match_subfolder(QuickSearch *quicksearch,
        GSList *msglist = folder_item_get_msg_list(src);
        GSList *cur;
        gboolean result = FALSE;
-       
+       gint num = 0, total = src->total_msgs;
+       statusbar_print_all(_("Searching in %s... \n"), 
+               src->path ? src->path : "(null)");
        for (cur = msglist; cur != NULL; cur = cur->next) {
                MsgInfo *msg = (MsgInfo *)cur->data;
+               statusbar_progress_all(num++,total, 50);
                if (quicksearch_match(quicksearch, msg)) {
                        procmsg_msginfo_free(msg);
                        result = TRUE;
@@ -849,6 +873,8 @@ static gboolean quicksearch_match_subfolder(QuickSearch *quicksearch,
                if (!quicksearch_is_active(quicksearch))
                        break;
        }
+       statusbar_progress_all(0,0,0);
+       statusbar_pop_all();
 
        g_slist_free(msglist);
        return result;
index 03166ef1eb23347f34d60f875628f689bf8ca938..17b208880fa332ecc12f648d3253b34e8e2e9975 100644 (file)
@@ -960,11 +960,16 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
 
        if (quicksearch_is_active(summaryview->quicksearch)) {
                GSList *not_killed;
-
+               gint num = 0, total = summaryview->folder_item->total_msgs;
+               statusbar_print_all(_("Searching in %s... \n"), 
+                       summaryview->folder_item->path ? 
+                       summaryview->folder_item->path : "(null)");
                not_killed = NULL;
                for (cur = mlist ; cur != NULL && cur->data != NULL ; cur = g_slist_next(cur)) {
                        MsgInfo * msginfo = (MsgInfo *) cur->data;
 
+                       statusbar_progress_all(num++,total, 50);
+
                        if (!msginfo->hidden && quicksearch_match(summaryview->quicksearch, msginfo))
                                not_killed = g_slist_prepend(not_killed, msginfo);
                        else
@@ -974,6 +979,9 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
                                break;
                        }
                }
+               statusbar_progress_all(0,0,0);
+               statusbar_pop_all();
+               
                hidden_removed = TRUE;
                if (quicksearch_is_running(summaryview->quicksearch)) {
                        /* only scan subfolders when quicksearch changed,