Subject: bug#15801: 24.3.50; bar scrolling freezes gtk emacs

From: Jarek Czekalski <[email-masked]>
Date: Sun, 08 Dec 2013 17:14:15 +0100

This time the posts consists of 3 parts: the poll, the bug, the patch.

THE POLL about reproducability

Jan - almost unable to reproduce using gtk 3.8.6 and 2 core Intel 
2.6GHz. On a faster machine never reproduced.
Steve Berman - can't touch the scroll bar without a freeze, gtk 3.10.2, 
AMD 3.4 GHz
Jarek - reproducing with a couple of scroll bar movements, gtk 3.8.x, 
Celeron 3GHz

So at least 2 people are reproducing easily, including me.

THE BUG in gtk

I submitted a bug in gtk [1], as I suspect the motion events compression 
introduced in 3.7.10 is responsible for the freeze. Unfortunately I 
cannot reproduce without Emacs. Simply inserting gtk main loop call 
inside motion event handler in gtk3demo app, plus some random delays, 
does not allow to freeze it. Maybe breaking the chain of motion events 
with something different is necessary.

In gtk 3.10 It will be possible to switch off the motion events 
compression, as it introduces also another problems, as reported in gtk 
bug [2], "motion_compression hurts precision for drawing". The switch is 
not planned to be merged into 3.8.

In my opinion gtk with clocks and motion compression does not make sure 
that the pausing/unpausing of events is always paired. Unpaired pause 
results in a freeze. However the requirements for the freeze may be very 
difficult to meet, thus the bug remains unproven.

[1] https://bugzilla.gnome.org/show_bug.cgi?id=719883
[2] https://bugzilla.gnome.org/show_bug.cgi?id=702392

THE PATCH for Emacs

Emacs is not free of bugs in this area. I consider a bug the behaviour, 
when inside a gtk signal handler (scroll bar event) we enter another gtk 
event loop.

That's because of (almost) undocumented feature of unblock_input. It 
does not only process the events that came during block/unblock pair, 
but it also processes the queue of events that were not processed 
before. Emacs seems to rely on calls to ublock_input, which trigger 
reading the input. A function without block/unblock statements would 
actually be never interrupted. When block/unblock pair is inserted, it 
will cause input handling at the moment of unblock_input call. That does 
not hurt much, as stated by Stephan in [3], but introduces a 
counter-intuitive feature: the function containing block/unblock is 
usually safer than the one not containing them. It is most important in 
callbacks. A callback containing block/unblock is unsafe, unless it is 
contained in an outer block/unblock pair.

The patch introduces block/unblock input wrapper around the glib main 
loop in xgselect.c, thus preventing main loop recursion. The recursion 
was occuring when unblock_input was called inside the scroll bar 
callback. Full backtrace attached.

This time I believe the patch is something that should be applied. It 
contains also comments, that should make some features better noticable. 
One of the comments is for unblock_input. I hope it's agreeable.

Jarek

[3] 
http://emacs.1067599.n5.nabble.com/GTK-stack-busting-loop-tp219788p219791.html