[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
wait_reading_process_output bug [Was RE: A question on wait_reading_proc
From: |
Herbert Euler |
Subject: |
wait_reading_process_output bug [Was RE: A question on wait_reading_process_output] |
Date: |
Thu, 29 May 2008 19:30:44 +0800 |
I think I can reproduce the problem now. Following the steps I will
introduce later, I see the problem, just as my guess.
I have attatched two files: x.c and x.el. In the file x.c, the key
logic is very simple, as listed below:
signal (SIGTERM, handle_interrupt);
while (keep_looping)
;
printf ("hello, world\n");
We will run this program inside Emacs and send a SIGTERM signal to its
process with "kill PID" at a proper point. That will make some output
available from the program and change its status to exit, so the code
of the body of the if will be executed, to reproduce the error.
The logic of x.el is also simple:
(let* ((buf (get-buffer-create "*test*"))
(proc (start-process "test" buf "/tmp/x")))
(when (accept-process-output proc 100 nil t)
(switch-to-buffer buf)))
"/tmp/x" here is the executable file, we will run it as an
asynchronous process, and try to read its output. We will not read
output from any other processes at the same time, as specified by the
last argument of the calling to `accept-process-output'. If
`accept-process-output' returns non-nil value, which means it reads
some output from the process according to its docstring, we will
switch to its output buffer. Otherwise, we stay at the buffer where
we were.
Now I will introduce how to reproduce the bug.
1. Copy the two files, x.el and x.c to /tmp. Compile x.c:
address@hidden:/tmp$ pwd
/tmp
address@hidden:/tmp$ cc -o x x.c
address@hidden:/tmp$ ls x*
x x.c x.el
address@hidden:/tmp$
2. Start Emacs in gdb:
(gdb) r -Q /tmp/x.el
Goto the end of the file and type C-x C-e to evaluate the let* form.
In another shell, kill the asynchronous process:
address@hidden:/tmp$ ps aux | grep /tmp/x$ | grep -v grep | awk '{ print
$2 }'
690
address@hidden:/tmp$ kill 690
address@hidden:/tmp$
The argument to kill is the process ID. The current buffer becomes
*test*. This is expected: `accept-process-output' returns non-nil, so
the current buffer is switched.
Now quit from Emacs by typing C-x C-c.
3. This time we will set a breakpoint at Faccept_process_output, so
that we can kill the asynchronous process at a proper point:
(gdb) b Faccept_process_output
Breakpoint 3 at 0x8253386: file process.c, line 3907.
(gdb)
And start Emacs in the same way:
(gdb) r -Q /tmp/x.el
4. Evaluate the let* form in x.el, gdb will take over the control.
Now set a breakpoint at process.c:4458, and continue the execution to
that point:
Breakpoint 3, Faccept_process_output (process=143107140, seconds=800,
millisec=138480921, just_this_one=138480969)
at process.c:3907
3907 int secs, usecs = 0;
(gdb) b process.c:4458
Breakpoint 4 at 0x8254347: file process.c, line 4458.
(gdb) c
Continuing.
Breakpoint 4, wait_reading_process_output (time_limit=100, microsecs=0,
read_kbd=0, do_display=0,
wait_for_cell=138480921, wait_proc=0x887a440, just_wait_proc=1) at
process.c:4458
4458 if (wait_proc && wait_proc->raw_status_new)
(gdb)
5. Kill the asynchronous process again. This will trigger the
condition reproducing the bug. In another shell, execute the
following commands:
address@hidden:/tmp$ ps aux | grep /tmp/x$ | grep -v grep | awk '{ print
$2 }'
5727
address@hidden:/tmp$ kill 5727
address@hidden:/tmp$
And, after killing the process, in the gdb shell, set another
breakpoint and continue the execution to that point:
(gdb) b process.c:4472
Breakpoint 5 at 0x8254591: file process.c, line 4472.
(gdb) c
Continuing.
Breakpoint 5, wait_reading_process_output (time_limit=100, microsecs=0,
read_kbd=0,
do_display=0, wait_for_cell=138481385, wait_proc=0x853a788,
just_wait_proc=1)
at process.c:4472
4472 nread = read_process_output (proc, wait_proc->infd);
(gdb)
The value of nread will be greater than 0, which means something has
been read from wait_proc's output:
(gdb) c
Continuing.
Breakpoint 5, wait_reading_process_output (time_limit=100, microsecs=0,
read_kbd=0,
do_display=0, wait_for_cell=138481385, wait_proc=0x853a788,
just_wait_proc=1)
at process.c:4472
4472 nread = read_process_output (proc, wait_proc->infd);
(gdb) n
4474 if (nread == 0)
(gdb) p nread
$1 = 13
(gdb)
wait_reading_process_output promises returning non-null value in such
a case. But the fact is not as described. Type finish in the gdb
shell to see this:
(gdb) finish
Run till exit from #0 wait_reading_process_output (time_limit=100,
microsecs=0, read_kbd=0,
do_display=0, wait_for_cell=138481385, wait_proc=0x853a788,
just_wait_proc=1)
at process.c:4472
0x0825375e in Faccept_process_output (process=139700108, seconds=800,
millisec=138481385,
just_this_one=138481433) at process.c:3946
3946 return
Value returned is $2 = 0
(gdb)
This $2 (0) becomes the value of evaluating accept-process-output.
Now delete all of the breakpoints and go back to the Emacs process:
(gdb) d
Delete all breakpoints? (y or n) y
(gdb) c
Continuing.
The current buffer remains #, not *test*. The behavior
here is not the same as said in step 2, and is not expected. Because
accept-process-output has read something, it should return a non-nil
value. But it does not.
Regards,
Guanpeng Xu
Btw, when I verify the steps to reproduce the bug, I find the
possibility it happens is not very small. I see the unexpected
behavior at least once without the helping of gdb.
_________________________________________________________________
Discover the new Windows Vista
http://search.msn.com/results.aspx?q=windows+vista&mkt=en-US&form=QBRE
x.c
Description: Text Data
x.el
Description: Text document
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- wait_reading_process_output bug [Was RE: A question on wait_reading_process_output],
Herbert Euler <=