+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
( 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
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=139
+EXTRA_VERSION=140
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
#include "folderview.h"
#include "folder.h"
#include "prefs_matcher.h"
+#include "sylpheed.h"
+#include "statusbar.h"
struct _QuickSearch
{
gpointer callback_data;
gboolean running;
gboolean has_focus;
+ gboolean matching;
+ gboolean deferred_free;
FolderItem *root_folder_item;
};
{
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;
}
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;
gboolean quicksearch_match(QuickSearch *quicksearch, MsgInfo *msginfo)
{
gchar *searched_header = NULL;
+ gboolean result = FALSE;
if (!quicksearch->active)
return TRUE;
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 */
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;
if (!quicksearch_is_active(quicksearch))
break;
}
+ statusbar_progress_all(0,0,0);
+ statusbar_pop_all();
g_slist_free(msglist);
return result;
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
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,