Permalink
Browse files

Fix hang during run-gimp when user clicks inside Emacs X window durin…

…g GIMP startup

Without this change, this is what happens inside `gimp-process' under
the condition that there is NOT any user input (meaning no X mouse
button clicks in the Emacs window, no X raise events on the Emacs
window via the window manager or anything else that might cause
Emacs's X event loop to sense input):

  The while loop continues to test for the prompt and initially
  doesn't find it, so it calls sit-for. sit-for dutifully waits for
  both terminal input and process output, and sees more process output
  from the GIMP process, and runs the current process filter which at
  this point is gimp-filter (sit-for returns non-nil in this case
  since process output occurred before the time-limit of 0.15 seconds
  expired). gimp-filter updates the gimp-output variable, and the
  while loop continues on.  Eventually the gimp-output variable
  contains the prompt, and the test matches the prompt, and the while
  loop terminates:

Again, without this change, this is what happens inside `gimp-process'
under the condition that there IS some user input:

  The while loop continues to test for the prompt and initially
  doesn't find it, so it calls sit-for. sit-for dutifully waits for
  both terminal input and process output, and sees more process output
  from the GIMP process, and runs the current process filter which at
  this point is gimp-filter. Suppose GIMP is slow to startup, so the
  prompt is not seen on the output, so gimp-filter updates the
  gimp-output variable to whatever process output it might see, and
  the while loop continues on.  At this point, say user inputs
  something into the Emacs window (e.g., raises the X window to the
  top of the window stack, or clicks into the window thus sending a
  mouse X event to the window), and the the while loop eventually
  calls sit-for again. This time sit-for detects user input, and
  immediately returns nil in this case, but does NOT call our process
  filter. Since sit-for is not waiting the requisite 0.15 seconds,
  gimp-filter is not even getting a chance to process output from GIMP
  even though the output is actually being sent! So the while loop
  goes infinite.

With this change, if sit-for returns nil, then discard-input is
called. This discards user input, which causes a subsequent execution
of sit-for to allow processing of process output.

Cautions about this change:

  Perhaps testing for sit-for returning nil is nonsensical. Maybe we
  just call discard-input all the time regardless of user input.

  What effect this has on C-g quiting is not known. It is not obvious
  to me at this point what the point was for allowing the user to quit
  out of the loop in the first place _other_ than to recover from this
  hang situation.  But discarding input with the call to discard-input
  doesn't seem to harm the quiting behavior anyhow.
  • Loading branch information...
1 parent 2f950e0 commit 296ca334d510975a5d271fb151e4250676f61ae3 @bgoodr bgoodr committed Oct 26, 2009
Showing with 6 additions and 1 deletion.
  1. +6 −1 gimp-mode.el
View
@@ -1225,7 +1225,12 @@ Optional argument END-TEXT is the text appended to the message when TEST fails."
(setq last-char 45))
(message "%s%c" (substring mess 0 (1- (length mess)))
(ring-next r last-char))
- (sit-for .15)))
+ ;; Discard any terminal input if sit-for returned immediately, thus forcing
+ ;; the gimp-filter function to get called with any new pending process
+ ;; input. What effect this has on the C-g quiting aspect is not known
+ ;; at this point:
+ (if (not (sit-for .15))
+ (discard-input))))
(if end-text (message "%s%s" (current-message) end-text))))
(defalias 'gimp-start 'run-gimp

0 comments on commit 296ca33

Please sign in to comment.