[net.emacs] Inferior process violates gnuemacs 1st ammendment?

tiemann@mcc-pp.UUCP (Michael Tiemann) (08/14/86)

So we *know* we're talking the same language, here's some simple
gnuemacs lisp code:

(defun setup-process (a &rest b)
  (interactive)
  (setq cat (eval (cons 'start-process (append (list a a a) b))))
  )

(defun send-process-region () 
  (interactive)
  (send-region cat (point) (mark))
  )

(defun cat ()
  (interactive)
  (setup-process "cat")
  (switch-to-buffer "cat")
)

(defun x-cat ()
  (interactive)
  (kill-buffer "cat")
)

(global-set-key "\e$" 'send-process-region)

Here's the problem: we set up at "cat" process (copy input to output),
find a big file, set point and mark to be 1000 characters apart, and
they repeatedly type "ESC-$" . 

On our SUN-3 about the 4th "ESC-4" the error message "writing to process:
operation would block, cat" pops up. If we continue to type "ESC-$",
the error sometimes comes up, and sometimes does not. On our VAX
11/750 "running" (walking) BDS 4.2, there is no error message, but the
gnuemacs shows up as Idle in ps -ux. (A few ^G's wake it into
abortion-land).

Clues? Look in process.c for the error-causing routine
(send_process_1). The problem gets worse: if I want to send a 10k
region, not even one call will go through. The code looks easy, so
either
	(1) I understand nothing about pipes.
	(2) The authors of GNU understand nothing about pipes
	(3) Our friends at Berkely understands nothing about pipes.
And its not "cat"'s fault: I wrote a program that just says "hello"
and then proceedes to read (and only read) the keyboard. Same result.

It seems to me that if I want to write a zillion bytes to a pipe, and
somebody else wants to read it, that the OS should wake and sleep us
until those zillion bytes have zipped through the pipe. If this is an
incorrect interpretation, please tell me how to pretend this is
happening.

Michael "God I wish I had shared memory" Tiemann

ehj@mordor.ARPA (Eric H Jensen) (08/14/86)

In article <1508@mcc-pp.UUCP> tiemann@mcc-pp.UUCP (Michael Tiemann) writes:
>On our SUN-3 about the 4th "ESC-4" the error message "writing to process:
>operation would block, cat" pops up. If we continue to type "ESC-$",
>the error sometimes comes up, and sometimes does not. On our VAX
>11/750 "running" (walking) BDS 4.2, there is no error message, but the
>gnuemacs shows up as Idle in ps -ux. (A few ^G's wake it into
>abortion-land).

I believe I had a similar problem to yours (GNUemacs 17.49).  The
cause is that emacs does an ioctl instructing unix that writes to the
pipe should not block (which, I believe, is for most purposes is the
right thing).  After thinking about it and consulting with our local
unix guru I came up with the following changes (hope this helps):


*** process.c.orig	Thu May 29 17:04:36 1986
--- process.c	Wed Jun  4 14:15:20 1986
***************
*** 166,171 ****
--- 166,174 ----
     Always -1 on systems that support FIONREAD.  */
  
  int proc_buffered_char[MAXDESC];
+ 
+ Lisp_Object Vwait_no_block;
+ 
  
  #ifdef HAVE_PTYS
  
***************
*** 1201,1206 ****
--- 1204,1217 ----
  {
    /* Don't use register vars; longjmp can lose them.  */
    int rv;
+   int fd;
+ 
+ #ifdef HAVE_TIMEVAL
+   struct timeval sd;
+   int usec;
+   int sv;
+ #endif /* HAVE_TIMEVAL */
+ 
    unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
  
    if ((XFASTINT (XPROCESS (proc)->flags) & PROC_STATUS) != RUNNING)
***************
*** 1211,1217 ****
    if (!setjmp (send_process_frame))
      while (len > 0)
        {
! 	rv = write (XFASTINT (XPROCESS (proc)->outfd), buf, len);
  	if (rv < 0)
  	  break;
  	buf += rv;
--- 1222,1239 ----
    if (!setjmp (send_process_frame))
      while (len > 0)
        {
! 	fd = XFASTINT (XPROCESS (proc)->outfd);
! 
! #ifdef HAVE_TIMEVAL
! 	if (XTYPE (Vwait_no_block) == Lisp_Int)
! 	  sd.tv_usec = XUINT (Vwait_no_block);
! 	else sd.tv_usec = 0;
! 	sd.tv_sec = 0;
! 	usec = 1 << fd;
! 	sv = select (fd + 1, 0,&usec, 0, &sd);
! #endif /* HAVE_TIMEVAL */
! 
! 	rv = write (fd, buf, len);
  	if (rv < 0)
  	  break;
  	buf += rv;
***************
*** 1694,1699 ****
--- 1716,1729 ----
    staticpro (&Qprocessp);
  
    staticpro (&Vprocess_alist);
+ 
+   DefLispVar ("wait-no-block", &Vwait_no_block,
+     "*If integer, unsigned value indicates number of microseconds \n\
+ for select to wait before writing to a subprocess. This mechanism \n\
+ is provided because Emacs refuses to block on writes to subprocesses.\n\
+ A non-integer value is equivalent to 0. The default value is 50000.");
+ 
+   Vwait_no_block = XFASTINT(50000);
  
    DefBoolVar ("delete-exited-processes", &delete_exited_processes,
      "*Non-nil means delete processes immediately when they exit.\n\




-- 
eric h. jensen        (S1 Project @ Lawrence Livermore National Laboratory)
Phone: (415) 423-0229 USMail: LLNL, P.O. Box 5503, L-276, Livermore, Ca., 94550
ARPA:  ehj@angband    UUCP:   ...!decvax!decwrl!mordor!angband!ehj

wesommer@mit-trillian.MIT.EDU (William Sommerfeld) (08/15/86)

Read the manual page for pipe(2) (this is BSD 4.3, but it hasn't
changed much).

     The pipe system call creates an I/O mechanism called a pipe.
     The file descriptors returned can be used in read and write
     operations.  When the pipe is written using the descriptor
     fildes[1] up to 4096 bytes of data are buffered before the
     writing process is suspended.  A read using the descriptor
     fildes[0] will pick up the data.

BUGS
     Should more than 4096 bytes be necessary in any pipe among a
     loop of processes, deadlock will occur.

In article <1508@mcc-pp.UUCP> tiemann@mcc-pp.UUCP writes:
>
>Here's the problem: we set up at "cat" process (copy input to output),
>find a big file, set point and mark to be 1000 characters apart, and
>they repeatedly type "ESC-$" . 
>
>On our SUN-3 about the 4th "ESC-4" the error message "writing to process:
>operation would block, cat" pops up. If we continue to type "ESC-$",
>the error sometimes comes up, and sometimes does not. On our VAX
>11/750 "running" (walking) BDS 4.2, there is no error message, but the
>gnuemacs shows up as Idle in ps -ux. (A few ^G's wake it into
>abortion-land).

It looks like you're jamming more than the maximum buffer size into
the pipe.  Since all "cat" does is whip your input back out at you,
and Emacs hasn't had a chance to read it yet, when both buffers get
jammed, you lose and have to break out.  It is possible that the SUN
kernel detects this deadlock situation and returns an EWOULDBLOCK
("Operation would block") error code.

>It seems to me that if I want to write a zillion bytes to a pipe, and
>somebody else wants to read it, that the OS should wake and sleep us
>until those zillion bytes have zipped through the pipe. If this is an
>incorrect interpretation, please tell me how to pretend this is
>happening.

Not if the kernel limits your buffer space; otherwise, runaway
processes could chew up all your memory.  The problem is not that
you're shipping a lot through the pipe, it is that you're shipping a
lot through, it's being sent right back to you, and you have no way to
read it because you're writing right now.

A possible fix (BSD dependant) would be to select non-blocking I/O,
maintain a queue of input for each file descriptor, and then ship
things over in 1K or 2K chunks, and drop back into a select loop when
the operation blocks.

					Bill Sommerfeld
				  ARPA: wesommer@athena.mit.edu
				  UUCP: ...!mit-eddie!wesommer