🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.bug
Article #98877

wait_reading_process_input () is not reentrant

#98877
From: Yutaka Niibe
Date: Fri, 25 Jan 1991 05:22
156 lines
5578 bytes
In GNU Emacs 18.55.5 of Thu Jan 24 1991 on naga.ee.uec.ac.jp (berkeley-unix)

This is BUG report.
Here we go.


* The function wait_reading_process_input () is not reentrant

  The function wait_reading_process_input () (in process.c) is not
  reentrant.  So, it may kill alive process wrongly.  It goes like:

  (1) First, wait_reading_process_input () is called.
  (2) Doing system call select (), variable Available is set to
  indicate which channels of outputs from processes are available.
  (3) Suppose, two channels are available and process of first channel
  has filter function which may call function like `sit-for',
  `sleep-for', `accept-process-output', or `read-char'.
  (4) It reads outputs from first channel, and call the filter
  function.
  (5) The filter function call `read-char' and
  wait_reading_process_input () is REENTERD.
  (6) Second wait_reading_process_input () does system call select (),
  and find second channel available.
  (7) Second wait_reading_process_input () reads from second channel,
  and works with it, and finally returns.
  (8) Now, we are in first wait_reading_process_input ().
  (9) First wait_reading_process_input () trys to read from second
  channel, but it find there is no data.
  (10) It thinks process of second channel has exited, and kills
  connection.  Oh unhappy second process!


* Example that generate wrong action

Here is example lisp expression that generate wrong action.
Please evaluate.

(let* ((i 0)
       (cat1 (start-process "cat1" nil "cat" "-"))
       (cat2 (start-process "cat2" nil "cat" "-"))
       )
  (set-process-filter cat1 '(lambda (proc str)
                              (message (substring str 0 -1))
                              (sit-for 1)))
  (set-process-filter cat2 '(lambda (proc str)
                              (ding)))
  (while (< i 10)
    (process-send-string cat1 (format "%d\n" i))
    (process-send-string cat2 "\n")
    (sleep-for 1)
    (setq i (1+ i)))
  (delete-process cat1)
  (delete-process cat2))

Expected action is showing message in echo area and dinging
10 time one after another.

But it stops with error `Process cat2 not running' because of
existence of `sit-for' in cat1's filter.

If you change order of starting processes like following example,
it works fine.

(let* ((i 0)
       (cat2 (start-process "cat2" nil "cat" "-"))
       (cat1 (start-process "cat1" nil "cat" "-"))
       )
     ...


* What's my warrant for saying it is `BUG'?

(1) GNU Emacs Lisp Reference Mannual (edition 1.02) says
(pp.480, 32.8.2 Process Filter Functions):

       A filter function must accept two arguments: the associated process
     and a string, which is the output.  The function is then free to do
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     whatever it chooses to with the output.
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(I added ^^.)

(2) There exist applications using filter that may invoke
wait_reading_process_input ().

Following list shows such applications I examined.

    In directory dist-18.55/lisp/:

    server.el
    server-process-filter --> server-visit-files --> y-or-n-p

    telnet.el
    telnet-initial-filter --> read-password --> read-char

    xscheme.el
    xscheme-process-filter   -->  xscheme-prompt-for-confirmation --> y-or-n-p
                          (funcall)

    and in another directory:

    ange-ftp.el
    ange-ftp-gwp-filter --> ange-ftp-get-passwd --> read-char
                        --> ange-ftp-get-user   --> read-string

* Patch

I add my proposal patch at the end of this bug report.  Only 7
characters are inserted.  I make the variable `Available' to be
`static'.  So, the function wait_reading_process_input () becomes
reentrant.

I think this solution is right.  Emacs works well with this patch, at
least my environment.


***
Finally, I want to express my special thanks to Richard M. Stallman
and FSF.  I love GNU Emacs very much.

Thanks.

Yutaka NIIBE

Department of Electronic Engineering
The University of Electro-Communications, Tokyo, Japan.
e-mail: niibe@naga.ee.uec.ac.jp  <-- valid until APRIL


=== patch goes from here ====
In case of emacs-18.55, output will be:
  Hunk #1 succeeded at 1289 (offset -70 lines).

In case of Nemacs-3.3.2, output will be:
  Hunk #1 succeeded at 1351 (offset -8 lines).

*** process.c~	Sat Jan 19 19:09:51 1991
--- process.c	Thu Jan 24 10:48:33 1991
***************
*** 1359,1365 ****
       int time_limit, read_kbd, do_display;
  {
    register int channel, nfds, m;
!   int Available = 0;
    int Exception;
    int xerrno;
    Lisp_Object proc;
--- 1359,1365 ----
       int time_limit, read_kbd, do_display;
  {
    register int channel, nfds, m;
!   static int Available = 0;
    int Exception;
    int xerrno;
    Lisp_Object proc;
=== end of patch ====
Technical Details
Message-ID: <9101250522.AA07749@naga.ee.uec.ac.jp>
Path: arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!naga.ee.uec.ac.jp!ytk

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: fb2f1,9abd62cf39e1b33,start
X-Google-Attributes: gidfb2f1,public
X-Google-ArrivalTime: 1991-01-24 21:22:10 PST
Path: arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!naga.ee.uec.ac.jp!ytk
From: ytk@naga.ee.uec.ac.jp (Yutaka Niibe)
Newsgroups: gnu.emacs.bug
Subject: wait_reading_process_input () is not reentrant
Message-ID: <9101250522.AA07749@naga.ee.uec.ac.jp>
Date: 25 Jan 91 05:22:10 GMT
Sender: daemon@tut.cis.ohio-state.edu
Distribution: gnu
Organization: GNUs Not Usenet
Lines: 156
Approved: bug-gnu-emacs@prep.ai.mit.edu