[Top][All Lists]

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

bug#7117: 23.2.2 mangles terminal escape sequences

From: Ryan Johnson
Subject: bug#7117: 23.2.2 mangles terminal escape sequences
Date: Thu, 30 Sep 2010 16:39:07 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20100802 Lightning/1.0b2 Thunderbird/3.1.2

 On 9/30/2010 1:37 PM, Ryan Johnson wrote:
 On 9/28/2010 6:53 AM, Ryan Johnson wrote:
 On 9/27/2010 10:52 PM, Stefan Monnier wrote:
Steps to reproduce:
   1. ssh to a machine with emacs-23 installed (I suspect slower
      networks would expose this more, but the bug bites me even over
2. compile tee-input.c (see below) into a shared library (on solaris:
      `cc -g -G -xcode=pic13 -ldl -hlibtee-input.so tee-input.c -g -o
   3. invoke `LD_PRELOAD=libtee-input.so emacs -nw -Q 2>input.txt'
   4. M-x xterm-mouse-mode
   5. flick the mouse scroll wheel hard, so it generates many ticks in
      quick succession (note the garbage that results)
   6. M-x show-lossage (note the mangled escape sequences)
   7. C-x C-c
   8. Examine input.txt (note the intact escape sequences)
Does (set-keyboard-coding-system 'binary) circumvent the problem?
No. In fact, the solaris machine which I ran the example on defaults to `no-conversion' (an alias of binary iirc) for some reason. Sorry, I forgot to mention before.

This matches my expectations, since bug #6920 arises before any coding system touches the input.
Any hints on where the problem might lurk? I poked around a little but without luck -- the functions that power read-char are many hundreds of lines long and seem to weave between lisp and C at regular intervals. I'm willing to go source diving but it's a bit daunting to wade into the C code again without a starting reference.
OK, I bit the bullet and fired up a debugger. I've narrowed down the problem some.

In keyboard.c, all keyboard input is buffered in kbd_buffer, which is a circular buffer with tail kbd_fetch_ptr. In all cases, when a control sequence gets mangled it's because kbd_fetch_ptr was incremented by more than one slot between iterations of the command loop (often by several dozen). However, it turns out that incrementing by more than one slot happens quite often and only sometimes exhibits the bug.

More digging shows that multiple increments are due to Fdiscard_input being called with the following stack trace:
=>[1] Fdiscard_input(), line 10947 in "keyboard.c"
[2] cmd_error_internal(data = -1059860928, context = 0xffbfee40 ""), line 1301 in "keyboard.c"
  [3] cmd_error(data = -1059860928), line 1234 in "keyboard.c"
[4] internal_condition_case(bfun = 0x111578 = &command_loop_1(), handlers = 1077839640, hfun = 0x109b8c = &cmd_error(register Lisp_Object data)), line 1480 in "eval.c"
  [5] command_loop_2(), line 1360 in "keyboard.c"
[6] internal_catch(tag = 1077836792, func = 0x10283c = &command_loop_2(), arg = 1077782856), line 1226 in "eval.c"
  [7] command_loop(), line 1339 in "keyboard.c"
  [8] recursive_edit_1(), line 954 in "keyboard.c"
  [9] Frecursive_edit(), line 1016 in "keyboard.c"
  [10] main(argc = 3, argv = 0xffbff374), line 1833 in "emacs.c"

At this point the symptom is easy enough to understand: sometimes discard-input gets unlucky and chops the front off of a partly-arrived escape sequence.

The real question is, why would the command loop encounter errors and need to discard input at all?
  [1] _longjmp()
=>[2] unwind_to_catch()
  [3] Fsignal()
  [4] xsignal()
  [5] xsignal0()
  [6] window_scroll()
  [7] scroll_command()
  [8] Fscroll_down()
  [9] Ffuncall()
  [10] Feval()
  [11] internal_lisp_condition_case()
  [12] Fbyte_code()
  [13] funcall_lambda()
  [14] Ffuncall()
  [15] Fapply()
  [16] apply1()
  [17] Fcall_interactively()
  [18] Ffuncall()
  [19] call3()
  [20] Fcommand_execute()
  [21] command_loop_1()
  [22] internal_condition_case()
  [23] command_loop_2()
  [24] internal_catch()
  [25] command_loop()
  [26] recursive_edit_1()
  [27] Frecursive_edit()
  [28] main()

From the above, it seems that scrolling past beginning or end of buffer triggers an error, which I guess is somewhat justifiable. However, on a very slow connection this morning mouse-clicking between or even within buffers caused problems. Unfortunately, setting debug-on-error doesn't seem to catch errors generated from C code.

I could try to break on longjmp over another slow connection, but with the number of times it gets called for other reasons this would be slow going...


reply via email to

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