🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.bug
Article #99533

bugs in emacs 18.55 (VMS version)

#99533
From: Scott S. Snyder
Date: Mon, 13 Aug 1990 10:16
251 lines
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!sss

Show 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