Subject: Re: bug#32986: 27.0.50; unexpected delay in while-no-input + accept-process-output

From: Eli Zaretskii <[email-masked]>
Date: Mon, 08 Oct 2018 18:05:57 +0300

> From: João Távora <[email-masked]>
> Date: Mon, 08 Oct 2018 11:48:01 +0100
> 
> I would expect while-no-input to break out of accept-process-output very
> quickly after user keyboard input.  These expectations are met except
> for some situations.

I think your expectations are incorrect.  My expectations are that if
you call accept-process-output with a timeout of 30 sec, then
while-no-input will return after 30 sec plus a small delay.  It's just
that in order to see this in action, your experiment must be done in a
"clean room", and that is not easy.

First, one basic fact: accept-process-output calls
wait_reading_process_output in a way that instructs it not to wait for
keyboard input, you can see that clearly in the code (read_kbd is
passed as zero).  This means that wait_reading_process_output will
call pselect with the timeout of 30 sec (in your case), and will wait
that long before it returns (unless there's a subprocess that gives us
some stuff).  So why would you expect while-no-input that calls
accept-process-output with that timeout to return earlier?

Maybe you expect while-no-input to interrupt the pselect call when you
press SPC?  But that's not how keyboard input works in Emacs.  In some
configurations (e.g., GUI frame on X), keyboard input indeed delivers
a signal to Emacs, but the signal handler just sets a flag and
returns, it doesn't jump out of the pselect call.  It is then the job
of the running Lisp code to check whether keyboard input is available,
and act accordingly: set the quit-flag, and then test that flag soon
enough to return from while-no-input.  But since the "running Lisp
code" is in this case stuck in the pselect call, it cannot do anything
before pselect returns, right?

Now to the "clean room" part: the reason why you don't always see this
30-sec delay is because there are several factors that "contaminate"
the picture:

  . timers -- these cause us to reduce the timeout until the
    expiration time of the next timer, so pselect returns earlier than
    after 30 sec
  . the first time wait_reading_process_output is called, it almost
    immediately checks for available keyboard input, before it calls
    pselect

Therefore, to see the 30-sec delay, you need:

  . stop all timers, which in "emacs -Q" means:
    . disable blink-cursor-mode
    . disable global-eldoc-mode
    . disable font-lock-mode
    . cancel the undo--auto-bindary-timer (I did that via list-timers)
  . type "C-u C-x C-e", wait for a few seconds, and only then type SPC

If I do all of the above, I see 30 sec plus a small delay every time I
run your 2nd test.

> I tried quickly pluggin GDB in at the right time, but I don't know if
> I'm using the right GDB (using msys's which is pretty slow) and I
> probably should be using an unoptimized Emacs.  Anyway, as a start this
> is what "bt full" look like:
> 
>    (gdb) bt full
>    #0  0x00007ffc97b0d8c1 in ntdll!DbgBreakPoint () from /c/WINDOWS/SYSTEM32/ntdll.dll
>    No symbol table info available.
>    #1  0x00007ffc97b39a0b in ntdll!DbgUiRemoteBreakin () from /c/WINDOWS/SYSTEM32/ntdll.dll
>    No symbol table info available.
>    #2  0x00007ffc952b3034 in KERNEL32!BaseThreadInitThunk ()
>       from /c/WINDOWS/System32/KERNEL32.DLL
>    No symbol table info available.
>    #3  0x00007ffc97ae1461 in ntdll!RtlUserThreadStart () from /c/WINDOWS/SYSTEM32/ntdll.dll
>    No symbol table info available.
>    #4  0x0000000000000000 in ?? ()

On Windows, when you attach a debugger to a program, the OS creates a
special thread in the debuggee, and that is the thread whose backtrace
you see here.  That thread is never an interesting one, so the first
thing you need to do after attaching is switch to the Lisp thread, by
typing "thread 1" at the GDB prompt.  Then the backtrace will make
much more sense.

>    Backtrace stopped: previous frame inner to this frame (corrupt stack?)
>    (gdb) xbacktrace
>    Undefined command: "xbacktrace".  Try "help".
> 
> xbacktrace probably failed because of some Python error loading .gdbinit

No, it says "Undefined command", which means it doesn't know what
xbacktrace is.  You probably didn't start GDB from the Emacs's src
directory, so it didn't read the .gdbinit file which defines that
command.  You can do that manually by typing the command

  (gdb) source /path/to/emacs/src/.gdbinit

(This last part is not specific to Widnows.)