emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: read_char() does not detect, handle special-event-map buffer changes


From: Derek Upham
Subject: Re: read_char() does not detect, handle special-event-map buffer changes
Date: Thu, 07 Feb 2013 20:39:42 -0800
User-agent: mu4e 0.9.9.5-dev6; emacs 24.2.2

Stefan Monnier writes:
>> in a separate terminal.  Move focus back to Emacs before the signal goes
>> out.  Hit `q' in the new buffer and Emacs will complain about "*foo*"
>> being read-only.  The second time you hit `q', Emacs will exit view mode
>> and bury the buffer.
>
> I think this is a known problem: the set of active keymaps is determined
> at the end of the previous command, so any change performed via
> something like a special-event-map binding or a process-filter will bump
> into this problem (you don't even need to switch-to-buffer, just
> enabling view-mode is sufficient).
>
> It's a bug: we should instead wait until the first key is pressed
> before figuring out the active keymaps.
> Problem is, this bug is in read_key_sequence, which is a pretty
> scary function.
>
> In the mean time, you can work around the bug by adding to
> unread-command-event (from your sigusr1-handler) a dummy event that is
> bound in global-map to something like `ignore'.
>
>
>         Stefan

Did you see my comment in the original email?  read_char() is already
trying to detect changed keymaps.

      if (current_buffer != prev_buffer)
        {
          /* The command may have changed the keymaps.  Pretend there
             is input in another keyboard and return.  This will
             recalculate keymaps.  */
          c = make_number (-2);
          goto exit;
        }
      else
        goto retry;

The bug is happening because the test is flawed: current_buffer and
prev_buffer are the same, so Emacs doesn't think it needs to recalculate
anything.  It loops back to the top of read_char() and reads another
character with the same keymap.

Removing the retry case and exiting every time fixes the problem:

      /* The command may have changed the keymaps.  Pretend there
         is input in another keyboard and return.  This will
         recalculate keymaps.  */
      c = make_number (-2);
      goto exit;

This removes a flawed optimization and returns a documented value.  It
doesn't touch read_key_sequence, so that risk goes away.  If we were
getting special events at a high rate of speed this /might/ cause a
slowdown, but nothing in the special events table seems to be used that
way---and I expect that the extra time spent popping back up to
read_key_sequence for the retry will still be very fast compared to the
time spent in the Emacs Lisp callback.

Derek

-- 
Derek Upham
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]