unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Jarek Czekalski <jarekczek@poczta.onet.pl>
To: 15801@debbugs.gnu.org
Subject: bug#15801: 24.3.50; bar scrolling freezes gtk emacs
Date: Sun, 08 Dec 2013 17:14:15 +0100	[thread overview]
Message-ID: <52A49AD7.9060605@poczta.onet.pl> (raw)
In-Reply-To: <5277EA95.4070001@poczta.onet.pl>

[-- Attachment #1: Type: text/plain, Size: 3025 bytes --]

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


[-- Attachment #2: reent_bt.txt --]
[-- Type: text/plain, Size: 13736 bytes --]

Script started on Sat 07 Dec 2013 10:43:18 AM CET
jcdeb:/m/usr/src/gtk+# gdb\b \b\b \b\b \bbs=1 gdb --args emacs -Q
GNU gdb (GDB) 7.6.1 (Debian 7.6.1-1)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/local/bin/emacs-24.3.50...done.
(gdb) start
Temporary breakpoint 1 at 0x80582f0: file ../../emacs-checkout/src/emacs.c, line 688.
Starting program: /usr/local/bin/emacs -Q
warning: Could not load shared library symbols for linux-gate.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/i686/cmov/libthread_db.so.1".

Temporary breakpoint 1, main (argc=2, argv=0xbffff554)
    at ../../emacs-checkout/src/emacs.c:688
688	{
(gdb) break gdkframeclockidle.c:329 if bsnested>1
Breakpoint 2 at 0xb78f59bf: file gdkframeclockidle.c, line 329.
(gdb) cont
Continuing.
[New Thread 0xb5f2db40 (LWP 17607)]
<[New Thread 0xb5554b40 (LWP 17609)]
[New Thread 0xb4bffb40 (LWP 17611)]
<m<>>mPmmmpmmmPmpmmmPpmmmP<p<m>mPmmmpmmPmp<m>mPmpmmmmPpmmPmmpmmmmPpm<m'mF'@mf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mF'@m'@mf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}mmPpm'mF'@mf(0mP{m)p}m'mF'@mf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}mmP'mF'@mf(0{m)p}mmP'mFpmf(0mP{m)p}m'mF'@mf(0mP{m)p}m'mF'@m'@mf(0mP{m)p}m'mF'@m'@mf(0mP{m)p}m'mFmP'@mf(0pmPpm'mF{mP)mfp}mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mFf(0mP{m)p}m'mF'@m'@mf(0mP{m)p}m'mFmP'@mf(0{m)p}m'mF'@m'@mf(0mP{m)p}m'mFf(0{mP)p}m'mFf(0{mP)p}m'mF'@mf(0mP{m)p}m'mF'@mf(0mP{m)p}m'mF'@mf(0mP{m)p}mmP'mFf(0pmPpm{mP)mp}m'mF'@m'@m'@mf(0'mFmPfpmFPf(1$
Breakpoint 2, gdk_frame_clock_flush_idle (data=0x85e4950)
    at gdkframeclockidle.c:329
329	  g_signal_emit_by_name (G_OBJECT (clock), "flush-events");
(gdb) bt
#0  gdk_frame_clock_flush_idle (data=0x85e4950) at gdkframeclockidle.c:329
#1  0xb78e7075 in gdk_threads_dispatch (data=data@entry=0x8a13230) at gdk.c:788
#2  0xb74810b1 in g_timeout_dispatch (source=source@entry=0x8a70ef0, 
    callback=0xb78e7040 <gdk_threads_dispatch>, user_data=0x8a13230)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:4413
#3  0xb748042e in g_main_dispatch (context=0x85cd918, context@entry=0x85bd9a0)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:3054
#4  g_main_context_dispatch (context=context@entry=0x85cd918)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:3630
#5  0xb74807d8 in g_main_context_iterate (context=context@entry=0x85cd918, 
    block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:3701
#6  0xb7480898 in g_main_context_iteration (context=0x85cd918, 
    context@entry=0x0, may_block=may_block@entry=1)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:3762
#7  0xb7aedbd8 in gtk_main_iteration () at gtkmain.c:1260
#8  0x080f13a1 in XTread_socket (terminal=0x8773c10, hold_quit=0xbfffdc9c)
    at ../../emacs-checkout/src/xterm.c:7077
#9  0x08125329 in gobble_input () at ../../emacs-checkout/src/keyboard.c:6841
#10 0x08124d05 in handle_async_input ()
    at ../../emacs-checkout/src/keyboard.c:7081
#11 process_pending_signals () at ../../emacs-checkout/src/keyboard.c:7095
#12 0x081264e3 in unblock_input () at ../../emacs-checkout/src/keyboard.c:7124
---Type <return> to continue, or q <return> to quit---
#13 0x080eeca8 in x_send_scroll_bar_event (window=<optimized out>, 
    part=<optimized out>, portion=<optimized out>, whole=whole@entry=1617275)
    at ../../emacs-checkout/src/xterm.c:4299
#14 0x080f0832 in xg_scroll_callback (range=range@entry=0x84c8220, 
    scroll=GTK_SCROLL_JUMP, value=value@entry=1980707.359550562, 
    user_data=user_data@entry=0x8a06838)
    at ../../emacs-checkout/src/xterm.c:4472
#15 0xb7aef2f3 in _gtk_marshal_BOOLEAN__ENUM_DOUBLE (closure=0x8a1f458, 
    return_value=0xbfffdee0, n_param_values=3, param_values=0xbfffdf50, 
    invocation_hint=0xbfffdefc, marshal_data=0x0) at gtkmarshalers.c:442
#16 0xb754b69e in g_closure_invoke (closure=0x8a1f458, 
    return_value=return_value@entry=0xbfffdee0, n_param_values=3, 
    param_values=param_values@entry=0xbfffdf50, 
    invocation_hint=invocation_hint@entry=0xbfffdefc)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gclosure.c:777
#17 0xb755d149 in signal_emit_unlocked_R (node=node@entry=0x84c5cc8, detail=0, 
    instance=0x84c8220, emission_return=emission_return@entry=0xbfffe010, 
    instance_and_params=0xbfffdf50)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gsignal.c:3584
#18 0xb7564884 in g_signal_emit_valist (instance=instance@entry=0x84c8220, 
    signal_id=signal_id@entry=152, detail=detail@entry=0, 
    var_args=0xbfffe0c8 "üàÿ¿\230u÷", var_args@entry=0xbfffe0bc "\001")
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gsignal.c:3338
---Type <return> to continue, or q <return> to quit---
#19 0xb7564dd3 in g_signal_emit (instance=instance@entry=0x84c8220, 
    signal_id=152, detail=detail@entry=0)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gsignal.c:3384
#20 0xb7b3f62a in update_slider_position (range=range@entry=0x84c8220, 
    mouse_x=<optimized out>, mouse_y=299) at gtkrange.c:2746
#21 0xb7b3fa4e in gtk_range_motion_notify (widget=0x84c8220, event=0x8519770)
    at gtkrange.c:2911
#22 0xb7aeec16 in _gtk_marshal_BOOLEAN__BOXEDv (closure=0x85bc6a8, 
    return_value=0xbfffe268, instance=0x84c8220, 
    args=0xbfffe33c "p\227Q\b\\ãÿ¿\020\227[\b\200dL\bh\017æ·çÒ·h\017æ· \202L\b", marshal_data=0xb7b3f990 <gtk_range_motion_notify>, n_params=1, 
    param_types=0x85bbdc8) at gtkmarshalers.c:130
#23 0xb754a077 in g_type_class_meta_marshalv (closure=0x85bc6a8, 
    return_value=0xbfffe268, instance=0x84c8220, 
    args=0xbfffe33c "p\227Q\b\\ãÿ¿\020\227[\b\200dL\bh\017æ·çÒ·h\017æ· \202L\b", marshal_data=0xcc, n_params=1, param_types=0x85bbdc8)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gclosure.c:997
#24 0xb754b8de in _g_closure_invoke_va (closure=closure@entry=0x85bc6a8, 
    return_value=return_value@entry=0xbfffe268, 
    instance=instance@entry=0x84c8220, 
    args=args@entry=0xbfffe33c "p\227Q\b\\ãÿ¿\020\227[\b\200dL\bh\017æ·çÒ·h\017æ· \202L\b", n_params=1, param_types=0x85bbdc8)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gclosure.c:840
---Type <return> to continue, or q <return> to quit---
#25 0xb7564237 in g_signal_emit_valist (instance=instance@entry=0x84c8220, 
    signal_id=signal_id@entry=32, detail=detail@entry=0, 
    var_args=var_args@entry=0xbfffe33c "p\227Q\b\\ãÿ¿\020\227[\b\200dL\bh\017æ·çÒ·h\017æ· \202L\b")
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gsignal.c:3234
#26 0xb7564dd3 in g_signal_emit (instance=instance@entry=0x84c8220, 
    signal_id=32, detail=detail@entry=0)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gsignal.c:3384
#27 0xb7c2d8fb in gtk_widget_event_internal (widget=widget@entry=0x84c8220, 
    event=event@entry=0x8519770) at gtkwidget.c:6722
#28 0xb7c2dbd5 in gtk_widget_event (widget=widget@entry=0x84c8220, 
    event=event@entry=0x8519770) at gtkwidget.c:6379
#29 0xb7aeca25 in propagate_event_up (topmost=<optimized out>, 
    event=<optimized out>, widget=0x84c8220) at gtkmain.c:2393
#30 propagate_event (widget=<optimized out>, event=0x8519770, captured=0, 
    topmost=0x0) at gtkmain.c:2501
#31 0xb7aee810 in gtk_main_do_event (event=0x8519770) at gtkmain.c:1716
#32 0xb78f052c in _gdk_event_emit (event=event@entry=0x8519770)
    at gdkevents.c:71
#33 0xb78ef0f8 in _gdk_display_flush_events (display=display@entry=0x85dc040)
    at gdkdisplay.c:2039
#34 0xb78fbec6 in gdk_window_flush_events (clock=0x85e4950, data=0x85e2980)
    at gdkwindow.c:11610
---Type <return> to continue, or q <return> to quit---
#35 0xb754d339 in g_cclosure_marshal_VOID__VOIDv (closure=0x853a2f8, 
    return_value=0x0, instance=0x85e4950, args=0xbfffe6b8 "\001", 
    marshal_data=0x0, n_params=0, param_types=0x0)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gmarshal.c:115
#36 0xb754b8de in _g_closure_invoke_va (closure=closure@entry=0x853a2f8, 
    return_value=return_value@entry=0x0, instance=instance@entry=0x85e4950, 
    args=args@entry=0xbfffe6b8 "\001", n_params=0, param_types=0x0)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gclosure.c:840
#37 0xb7564237 in g_signal_emit_valist (instance=instance@entry=0x85e4950, 
    signal_id=signal_id@entry=136, detail=detail@entry=0, 
    var_args=var_args@entry=0xbfffe6b8 "\001")
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gsignal.c:3234
#38 0xb7565291 in g_signal_emit_by_name (instance=instance@entry=0x85e4950, 
    detailed_signal=detailed_signal@entry=0xb7934e13 "flush-events")
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./gobject/gsignal.c:3424
#39 0xb78f59d1 in gdk_frame_clock_flush_idle (data=0x85e4950)
    at gdkframeclockidle.c:329
#40 0xb78e7075 in gdk_threads_dispatch (data=data@entry=0x8a13390) at gdk.c:788
#41 0xb74810b1 in g_timeout_dispatch (source=source@entry=0x85550c0, 
    callback=0xb78e7040 <gdk_threads_dispatch>, user_data=0x8a13390)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:4413
#42 0xb748042e in g_main_dispatch (context=0x85cd918, context@entry=0xb753c000)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:3054
---Type <return> to continue, or q <return> to quit---
#43 g_main_context_dispatch (context=context@entry=0x85cd918)
    at /build/glib2.0-Ot8bbC/glib2.0-2.36.4/./glib/gmain.c:3630
#44 0x081ff178 in xg_select (fds_lim=<optimized out>, rfds=0xbfffed70, 
    wfds=0xbfffedf0, efds=0x0, timeout=0xbfffe7c8, sigmask=0x0)
    at ../../emacs-checkout/src/xgselect.c:147
#45 0x081cb30b in wait_reading_process_output (time_limit=<optimized out>, 
    nsecs=0, read_kbd=read_kbd@entry=-1, do_display=do_display@entry=true, 
    wait_for_cell=138861506, wait_proc=wait_proc@entry=0x0, 
    just_wait_proc=just_wait_proc@entry=0)
    at ../../emacs-checkout/src/process.c:4584
#46 0x08062595 in sit_for (timeout=timeout@entry=120, 
    reading=reading@entry=true, display_option=display_option@entry=1)
    at ../../emacs-checkout/src/dispnew.c:5800
#47 0x081292a6 in read_char (commandflag=1, map=map@entry=142392614, 
    prev_event=138861506, used_mouse_menu=used_mouse_menu@entry=0xbffff25b, 
    end_time=end_time@entry=0x0) at ../../emacs-checkout/src/keyboard.c:2805
#48 0x0812a8a8 in read_key_sequence (keybuf=keybuf@entry=0xbffff308, 
    prompt=138861506, dont_downcase_last=false, dont_downcase_last@entry=10, 
    can_return_switch_frame=can_return_switch_frame@entry=true, 
    fix_current_buffer=fix_current_buffer@entry=true, prevent_redisplay=false, 
    prevent_redisplay@entry=10, bufsize=30)
    at ../../emacs-checkout/src/keyboard.c:9074
#49 0x0812b9d6 in command_loop_1 () at ../../emacs-checkout/src/keyboard.c:1445
---Type <return> to continue, or q <return> to quit---
#50 0x0818d3aa in internal_condition_case (
    bfun=bfun@entry=0x812b820 <command_loop_1>, handlers=138894602, 
    hfun=hfun@entry=0x8123260 <cmd_error>)
    at ../../emacs-checkout/src/eval.c:1344
#51 0x08121515 in command_loop_2 (ignore=ignore@entry=138861506)
    at ../../emacs-checkout/src/keyboard.c:1170
#52 0x0818d2cd in internal_catch (tag=138892650, 
    func=func@entry=0x81214f0 <command_loop_2>, arg=138861506)
    at ../../emacs-checkout/src/eval.c:1108
#53 0x08122e72 in command_loop () at ../../emacs-checkout/src/keyboard.c:1149
#54 recursive_edit_1 () at ../../emacs-checkout/src/keyboard.c:777
#55 0x0812314b in Frecursive_edit () at ../../emacs-checkout/src/keyboard.c:841
#56 0x08058e28 in main (argc=<optimized out>, argv=0xbffff554)
    at ../../emacs-checkout/src/emacs.c:1598
(gdb) quit
A debugging session is active.

	Inferior 1 [process 17567] will be killed.

Quit anyway? (y or n) y
jcdeb:/m/usr/src/gtk+# exit
exit

Script done on Sat 07 Dec 2013 10:44:12 AM CET

[-- Attachment #3: scroll_freeze_2_0.txt --]
[-- Type: text/plain, Size: 3623 bytes --]

=== modified file 'src/ChangeLog'
*** src/ChangeLog	2013-12-08 08:05:36 +0000
--- src/ChangeLog	2013-12-08 16:00:41 +0000
***************
*** 1,3 ****
--- 1,9 ----
+ 2013-12-08  Jarek Czekalski  <jarekczek@poczta.onet.pl>
+ 
+ 	Fix freezing with scroll bars of GTK3 Toolkit (Bug#15801).
+ 	* keyboard.c: A comment to unblock_input.
+ 	* xgselect.c: Prevent Glib main loop recursion.
+ 
  2013-12-08  Paul Eggert  <eggert@cs.ucla.edu>
  
  	Use libcrypto's checksum implementations if available, for speed.

=== modified file 'src/keyboard.c'
*** src/keyboard.c	2013-12-07 23:04:10 +0000
--- src/keyboard.c	2013-12-08 15:20:00 +0000
*************** unblock_input_to (int level)
*** 7118,7124 ****
  /* End critical section.
  
     If doing signal-driven input, and a signal came in when input was
!    blocked, reinvoke the signal handler now to deal with it.  */
  
  void
  unblock_input (void)
--- 7118,7129 ----
  /* End critical section.
  
     If doing signal-driven input, and a signal came in when input was
!    blocked, reinvoke the signal handler now to deal with it.
! 
!    It will also process queued input, if it was not read before.
!    When a longer code sequence does not use block/unblock input
!    at all, the whole input gathered up to the next call to
!    unblock_input will be processed inside that call. */
  
  void
  unblock_input (void)

=== modified file 'src/xgselect.c'
*** src/xgselect.c	2013-08-27 19:36:28 +0000
--- src/xgselect.c	2013-12-08 15:52:28 +0000
*************** along with GNU Emacs.  If not, see <http
*** 28,33 ****
--- 28,44 ----
  #include <timespec.h>
  #include "frame.h"
  
+ /* xg_select is a pselect replacement. Why do we need a separate function?
+    1. Timeouts. Glib and Gtk rely on timer events. If we did pselect
+       with a greater timeout then the one scheduled by Glib, we would
+       not allow Glib to process its timer events. We want Glib to
+       work smoothly, so we need to reduce our timeout to match Glib.
+    2. Descriptors. Glib may listen to more file descriptors than we do.
+       So we add Glib descriptors to our pselect pool, but we don't change
+       the value returned by the function. The return value  matches only
+       the descriptors passed as arguments, making it compatible with
+       plain pselect. */
+ 
  int
  xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
  	   struct timespec const *timeout, sigset_t const *sigmask)
*************** xg_select (int fds_lim, fd_set *rfds, fd
*** 45,56 ****
    int i, nfds, tmo_in_millisec;
    USE_SAFE_ALLOCA;
  
-   /* Do not try to optimize with an initial check with g_main_context_pending
-      and a call to pselect if it returns false.  If Gdk has a timeout for 0.01
-      second, and Emacs has a timeout for 1 second, g_main_context_pending will
-      return false, but the timeout will be 1 second, thus missing the gdk
-      timeout with a lot.  */
- 
    context = g_main_context_default ();
  
    if (rfds) all_rfds = *rfds;
--- 56,61 ----
*************** xg_select (int fds_lim, fd_set *rfds, fd
*** 132,139 ****
--- 137,149 ----
  #ifdef USE_GTK
        if (retval == 0)
  #endif
+         /* Prevent g_main_dispatch recursion, that would occur without
+            block_input wrapper, because event handlers call
+            unblock_input. Event loop recursion was causing Bug#15801. */
+         block_input();
          while (g_main_context_pending (context))
            g_main_context_dispatch (context);
+         unblock_input();
  
        /* To not have to recalculate timeout, return like this.  */
        if (retval == 0)


  parent reply	other threads:[~2013-12-08 16:14 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-04 18:42 bug#15801: 24.3.50; bar scrolling freezes gtk emacs Jarek Czekalski
2013-11-05 12:57 ` bug#15801: 15801: commit identified Jarek Czekalski
2013-11-06 19:48 ` bug#15801: it's a different revision, 112892 Jarek Czekalski
2013-11-21  6:00   ` Jan Djärv
2013-11-21  7:25     ` bug#15801: 24.3.50; bar scrolling freezes gtk emacs Jarek Czekalski
2013-11-30 11:41       ` Jan Djärv
2013-11-30 11:54         ` Eli Zaretskii
2013-11-30 12:51           ` Jan Djärv
2013-11-30 13:55             ` Eli Zaretskii
2013-11-30 14:05               ` Jan Djärv
2013-11-30 18:11               ` Jarek Czekalski
2013-11-30 18:38                 ` Eli Zaretskii
2013-11-30 17:04 ` Jarek Czekalski
2013-11-30 23:16   ` Jan Djärv
     [not found]     ` <529AF507.5080509@poczta.onet.pl>
     [not found]       ` <0440E2A5-37C6-4F29-9B5D-38A6AE88C3B5@swipnet.se>
     [not found]         ` <529B12DB.6020407@poczta.onet.pl>
2013-12-01 11:07           ` Jan Djärv
2013-12-01 11:38             ` Jarek Czekalski
2013-12-01 11:48               ` Jan Djärv
2013-11-30 17:10 ` bug#15801: 24.3.50; bar scrolling freezes gtk emacs - stdout warning Jarek Czekalski
2013-12-02  8:04 ` bug#15801: 24.3.50; bar scrolling freezes gtk emacs Jarek Czekalski
2013-12-02  8:18 ` Jarek Czekalski
2013-12-02 17:11 ` Jarek Czekalski
2013-12-03 22:27 ` Jarek Czekalski
2013-12-04 20:28 ` Jarek Czekalski
2013-12-05 17:08   ` Jarek Czekalski
2013-12-07 14:34     ` Jan Djärv
2013-12-08 16:14 ` Jarek Czekalski [this message]
2013-12-08 23:29 ` Jarek Czekalski
2013-12-11 19:52   ` Jan Djärv
2013-12-20  6:32   ` Jarek Czekalski
2013-12-20  8:58     ` Eli Zaretskii
2014-04-21 10:34 ` Jarek Czekalski
2014-04-21 15:56   ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52A49AD7.9060605@poczta.onet.pl \
    --to=jarekczek@poczta.onet.pl \
    --cc=15801@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).