[Users] [Bug 3375] Crash (SEGV) at gtkcmctree.c:4514 after deleting an unread message

noreply at thewildbeast.co.uk noreply at thewildbeast.co.uk
Sat Jan 31 20:43:07 CET 2015


http://www.thewildbeast.co.uk/claws-mail/bugzilla/show_bug.cgi?id=3375

--- Comment #4 from Deweloper <deweloper at wp.pl> ---
It happened again, this time on a 32-bit system.

(gdb) bt
#0  summary_set_row_marks (summaryview=summaryview at entry=0x8630d18, 
    row=row at entry=0x893a890) at summaryview.c:3833
#1  0x081bc685 in msginfo_mark_as_read (summaryview=0x8630d18, 
    msginfo=<optimized out>, row=0x893a890) at summaryview.c:3534
#2  0x081bc755 in msginfo_mark_as_read_timeout (data=data at entry=0x85a0870)
    at summaryview.c:3551
#3  0x49f52262 in g_timeout_dispatch (source=source at entry=0x8cda3a0, 
    callback=0x81bc700 <msginfo_mark_as_read_timeout>, user_data=0x85a0870)
    at gmain.c:4451
#4  0x49f51556 in g_main_dispatch (context=0x84a1638) at gmain.c:3066
#5  g_main_context_dispatch (context=context at entry=0x84a1638) at gmain.c:3642
#6  0x49f51920 in g_main_context_iterate (context=0x84a1638, 
    block=block at entry=1, dispatch=dispatch at entry=1, self=<optimized out>)
    at gmain.c:3713
#7  0x49f51dc3 in g_main_loop_run (loop=loop at entry=0x8411980) at gmain.c:3907
#8  0x41740720 in IA__gtk_main () at gtkmain.c:1257
#9  0x08082e44 in main (argc=1, argv=0xbffff1e4) at main.c:1559

Let's have a look at this:

(gdb) print msginfo
$1 = (MsgInfo *) 0x1
(gdb) print row
$2 = (GtkCMCTreeNode *) 0x893a890
(gdb) print summaryview->selected
$16 = (GtkCMCTreeNode *) 0x87bac90

Frame #2 passes summaryview->selected as row, but as you can see above, row !=
summaryview->selected in frame #1.

It seems that this is possible because msginfo_mark_as_read_timeout() (called
from a Glib timeout) is completely unsynchronized with
msginfo_mark_as_read_timeout() (called from a Gtk signal handler for
GDK_KEY_Delete). So summary_delete() might call summary_select_node() which
calls summary_cancel_mark_read_timeout() but this may fail to cancel the
timeout if another thread has already started execution of timeout handler.
Timeout handler calls summary_set_row_marks() (as seen on backtrace above) with
old value of "selected", which is stored on stack. Then GDK_KEY_Delete handler
replaces summaryview->selected with new value and destroys old selected row.
Then context switches to timeout handler which tries to use the old (already
destroyed) row.

I'm not familiar with Glib/Gtk - if that scenario is impossible please explain
how it was supposed to be synchronized (I mean, handling Delete key vs. "mark
as read" timeout).
According to
https://www.gnu.org/software/guile-gnome/docs/gdk/html/Threads.html :
"Callbacks from GTK+ signals are made within the GTK+ lock. However callbacks
from GLib (timeouts, IO callbacks, and idle functions) are made outside of the
GTK+ lock. So, within a signal handler you do not need to call
gdk-threads-enter, but within the other types of callbacks, you do. "
In summaryview.c msginfo_mark_as_read_timeout() - a timeout callback - doesn't
seem to call gdk-threads-enter (whatever it is).
summaryview.c also doesn't seem to synchronize cancelling the "mark as read"
timeout properly, as described under
https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-source-remove
. Isn't it also necessary to use g_source_is_destroyed as explained in 
https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-source-is-destroyed
?

-- 
You are receiving this mail because:
You are the assignee for the bug.



More information about the Users mailing list