trackerd ingores SIGINT when scanning Evolution email for junk
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
tracker (Ubuntu) |
Triaged
|
Undecided
|
Unassigned |
Bug Description
Binary package hint: tracker
Affects Hardy Intrepid Jaunty
When a trackerd process is running, and is re-indexing Evolution IMAP4 email headers (maybe other scenarios too) in
src/trackerd/
sending a SIGINT to the process fails to stop the process although the main thread does seem to receive and acknowledge the signal.
$ trackerd &
deleting email email:/
deleting email email:/
deleting email email:/
$ killall -s INT trackerd
Received signal Interrupt
Received signal 'Interrupt' so now shutting down
Total allocations = 835, total deallocations = 835
deleting email email:/
deleting email email:/
deleting email email:/
Analysis (please allow for context or typo issues, although I hope I've been accurate here with copy/paste):
When the INT signal is received there is code executing in src/trackerd/ trackerd. c::process_ files_thread( ):
if( tracker- >index_ status != INDEX_FINISHED) { ... switch (tracker- >index_ status) { ... case INDEX_EMAILS:
if (tracker- >index_ evolution_ emails || tracker- >index_ kmail_emails || tracker- >index_ thunderbird_ emails) { email_add_ service_ directories (db_con->emails)
tracker_
In src/trackerd/ tracker- email.c: :tracker_ email_add_ service_ directories( ) it follows:
if (tracker- >index_ evolution_ emails) { init_module ()) { watch_emails (db_con);
if (evolution_
evolution_
}
}
In src/trackerd/ tracker- email-evolution ::evolution_ watch_emails () it executes:
if (store) { summary_ file (db_con, row[2], store);
check_
which leads to src/trackerd/ tracker- email-evolution ::check_ summary_ file() where it scans for 'junk' headers and repeatedly executes this loop:
if (scan_summary_ for_junk (summary, &uid, store->type)) {
if (uid > 0) {
gchar *uri, *str_uid;
str_uid = tracker_uint_to_str (uid);
tracker_ db_email_ insert_ junk (db_con, path, uid);
uri = g_strconcat (store->uri_prefix, str_uid, NULL);
tracker_ db_email_ delete_ email (db_con, uri);
g_free (uri);
g_free (str_uid);
}
The problem is, where there are a *large* number of existing headers the scanning can take 1/2 hour or more. In the example case:
$ pwd .evolution/ mail/imap/ tjworld. net@pella/ folders/ Subscribed Lists/subfolder s/video4linux
/home/tj/
ls *.HEADER | wc -l
2084
In src/trackerd/ trackerd. c::signal_ handler( ) it does:
g_timeout_add_full (G_PRIORITY_LOW, 1, (GSourceFunc) tracker_do_cleanup, g_strdup (g_strsignal (signo)), NULL);
In src/trackerd/ trackerd/ c::tracker_ do_cleanup( ) it does:
/* set kill timeout */
g_timeout_add_full (G_PRIORITY_LOW, 20000, (GSourceFunc) tracker_die, NULL, NULL);
But even after that 20,000 milliseconds tracker_die() doesn't kill the process.
The issue seems to be that src/trackerd/ trackerd. c::process_ files_thread( ) does
sigset_t signal_set;
sigfillset (&signal_set);
which effectively disables all signals (since signal_set will be initialised to zero by the compiler).
Potentially long-running operations should enable signals and handle them gracefully.