Article View: gnu.emacs.bug
Article #99533bugs in emacs 18.55 (VMS version)
From: Scott S. Snyder
Date: Mon, 13 Aug 1990 10:16
Date: Mon, 13 Aug 1990 10:16
251 lines
10406 bytes
10406 bytes
I have observed the following bugs in Emacs 18.55 on VMS V5.3, compiled
with GCC 1.36:
1. Emacs can hang when exiting a process if another process is active.
Start Emacs with the `-q' switch, start a subprocess by typing
`(spawn-subprocess 2) LFD' in the *scratch* buffer, start another
subprocess with `M-$' (subprocess-command), then stop that process
by typing `eoj' (in the *COMMAND* buffer). Emacs will hang until ^G
is typed.
The problem here seems to be in process_exit (vmsfns.c). The loop
traversing the process list looks like:
ptr = process_list;
while (ptr)
{
if (! ptr->process_active)
{
next = ptr->next;
.
. delete process_list struct pointed to by ptr
.
}
prev = ptr;
ptr = next;
}
If the struct to be deleted is not at the head of the list, this code will
loop forever. This can be fixed by moving the line `next = ptr->next'
to immediately before the test.
It also seems to me that, since ptr is left pointing to the freed struct at
the end of the if statement, in the (admittedly unlikely) event that two
consecutive list elements are to be deleted simultaneously, the process list
could become corrupted. I believe that placing the statement `ptr = prev'
at the end of the conditional (immediately after the call to free()).
--------------------
2. Emacs hangs after starting a subprocess if a process with the same
Emacs ID code was stopped immediately beforehand.
Start Emacs with `-q'. Type in *scratch*: `(spawn-subprocess 2) LFD'
followed by `(progn (stop-subprocess 2) (start-subprocess 2)) LFD'.
Emacs will hang until ^G is typed. Now type `(stop-subprocess 2) LFD'.
Emacs aborts from sys_free().
This is a problem in Fspawn_subprocess (vmsfns.c). Suppose that process n
was just killed by stop-subprocess. Its process_list struct is marked as
inactive, but it is not actually removed from the process list until Emacs
is waiting for keyboard input again. If, before this happens, spawn-subprocess
is called with the same id number, the process list will be corrupted.
spawn-subprocess includes this piece of code, apparently intended to reuse
process_list structs in situations like this:
ptr = 0;
for (p = process_list; p; p = p->next)
if (p->name == XFASTINT (name))
{
ptr = p;
if (p->process_active)
return Qt;
else
sys$dassgn (p->mbx_chan);
break;
}
if (! ptr)
ptr = xmalloc (sizeof (struct process_list));
Later on in the code, ptr is linked into process_list with the statements:
ptr->next = process_list;
ptr->process_active = 1;
process_list = ptr;
However, if ptr was already on the process list, this will create a loop!
This can be fixed by delinking the struct from the list when we recognize it:
ptr = prev = 0;
for (p = process_list; p; prev=p, p = p->next)
if (p->name == XFASTINT (name))
{
ptr = p;
if (p->process_active)
return Qt;
else {
sys$dassgn (p->mbx_chan);
if (prev)
prev->next = p->next;
else
process_list = p->next;
}
break;
}
(where prev is declared as a struct process_list *).
--------------------
3. Emacs doesn't read process input that arrives while it is suspended.
Start a ``kept'' Emacs with `-q'. Type `M-$' to start a subprocess, then
type a command that will produce a fair amount of output (more than about
160 bytes - such as a directory of [.src]). Immediately after pressing
return, suspend Emacs with `C-Z'. Wait several seconds, then resume Emacs.
The output from the command does not appear. Further, the process will not
respond to any further input typed in the *COMMAND* buffer.
Emacs also will not recognize a process which exits while Emacs is suspended.
The problem here is that the event flag telling Emacs that something
interesting has happened with a subprocess gets cleared when Emacs is
resumed. In init_sys_modes (sysdep.c):
if (!process_ef)
LIB$GET_EF (&process_ef);
SYS$CLREF (process_ef);
This can be fixed by clearing the flag only on the first time through:
if (!process_ef) {
LIB$GET_EF (&process_ef);
SYS$CLREF (process_ef);
}
--------------------
4. After a subprocess of Emacs exits, Emacs can hog all available CPU time.
Start Emacs with `-q', spawn a subprocess with `M-$', then type `eoj RET'.
Emacs will start using all the CPU time that it can.
What's happening is that Emacs sets the VMS event flag process_ef when
input is received from a subprocess or when a subprocess exits. Emacs then
waits for this flag (along with input_ef) in wait_for_kbd_input (sysdep.c).
However, the event flag is not cleared after a process exit!
This can be fixed without introducing any potential timing errors (I hope!)
by adding a call to sys$clref in wait_for_kbd_input():
SYS$WFLOR (input_ef, input_eflist);
if (!detect_input_pending ())
/* Check for subprocess input availability */
{
int dsp = have_process_input || process_exited;
sys$clref(process_ef);
if (have_process_input)
process_command_input ();
--------------------
5. directory-file-name crashes when expanding a logical name with a long
equivalence string.
From DCL, define a logical name with a long equivalence string, such as
define foo a_very_long_equivalence_string_that_just_goes_on_and_on
Start Emacs with `-q' and type in *scratch* `(directory-file-name "foo:") LFD'.
Emacs dies horribly with an improperly handled access violation and the
last-chance handler register dump.
In Fdirectory_file_name() (fileio.c), space is allocated for the resultant
string via alloca(). The length of this buffer is the length of the original
string + 20:
buf = (char *) alloca (XSTRING (directory)->size + 20);
directory_file_name (XSTRING (directory)->data, buf);
return build_string (buf);
However, on VMS directory_file_name() can involve translating a logical
name, and equivalence strings can be up to 255 characters long. Thus, a
long equivalence string can overwrite the stack (since the buffer was gotten
with alloca()), creating all sorts of havoc. Since it appears that
directory_file_name() will only translate a logical name once (though
I didn't work through all the blecchy detail in directory_file_name(),
so I'm not certain), it should be safe to just increase the buffer size
by the maximum length of an equivalence string:
#ifdef VMS
/* 20 extra chars is insufficient for VMS, since we might perform a
logical name translation. an equivalence string can be up to 255
chars long, so grab that much extra space... - sss */
buf = (char *) alloca (XSTRING (directory)->size + 20 + 255);
#else
buf = (char *) alloca (XSTRING (directory)->size + 20);
#endif
--------------------
6. Emacs aborts when quitting during a redisplay triggered by subprocess input.
Start Emacs with `-q' and start a subprocess with `M-$'. Enter a command which
will generate a lot of output (such as a listing of the Emacs source
directory). While the output is being displayed, type C-G. Emacs traps to
the debugger.
! module name routine name line rel PC abs PC
!*SYSDEP sys_abort 1880 00000013 00067FFB
!*DISPNEW quit_error_check 712 00000011 00059A2F
!*KEYBOARD quit_throw_to_get_char 1829 00000009 00064C45
!*KEYBOARD interrupt_signal 1820 00000190 00064C34
!*KEYBOARD kbd_buffer_store_char 899 00000026 00063F12
!*SYSDEP kbd_input_ast 1123 00000056 000679B2
! 00000000 802690F3
!*TERM write_chars 598 000000DD 00060D57
!*DISPNEW update_line 898 000001C2 00059D68
!*DISPNEW update_screen 631 0000017E 000597AE
!*XDISP DoDsp 422 0000034C 0005B412
!*SYSDEP wait_for_kbd_input 1162 000000A0 00067A5A
!*KEYBOARD kbd_buffer_get_char 942 0000003B 00063FB7
!*KEYBOARD get_char 799 000001B9 00063D1B
!*KEYBOARD read_key_sequence 1301 0000005F 000640AF
!*KEYBOARD command_loop_1 551 000000FF 000637AF
!*EVAL internal_condition_case 996 00000097 0007D2E3
!*KEYBOARD command_loop_2 431 00000017 00063529
!*EVAL internal_catch 814 00000066 0007CF2A
!*KEYBOARD command_loop 413 0000004D 000634FB
!*KEYBOARD Frecursive_edit 301 00000093 00063255
!*EMACS main 461 000003BE 00062D48
The problem is that in keyboard.c, waiting_for_input is set before calling
wait_for_kbd_input. However, wait_for_kbd_input can call the Lisp evaluator
and the display code. If a quit is received during evaluation or redisplay,
Emacs aborts. The fix for this is to remove the calls to set_waiting_for_input
and clear_waiting_for_input from kbd_buffer_get_char in keyboard.c and
move them to just around the $wflor call in wait_for_kbd_input.
--------------------
Finally, I found that I had to make numerous small changes in order to get
Emacs to compile with GCC. If no one else has done so, I'd be happy to
send a set of diffs.
Scott Snyder
sss@max.physics.sunysb.edu
Technical Details
Message-ID:
<9008131016.AA12354@max.physics.sunysb.edu>Path:
arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!MAX.PHYSICS.SUNYSB.EDU!sssShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fb2f1,17ff4fe6e313178d,start X-Google-Attributes: gidfb2f1,public X-Google-ArrivalTime: 1990-08-13 03:16:49 PST Path: arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!MAX.PHYSICS.SUNYSB.EDU!sss From: sss@MAX.PHYSICS.SUNYSB.EDU (Scott S. Snyder) Newsgroups: gnu.emacs.bug Subject: bugs in emacs 18.55 (VMS version) Message-ID: <9008131016.AA12354@max.physics.sunysb.edu> Date: 13 Aug 90 10:16:49 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 251 Posted: Mon Aug 13 11:16:49 1990