[comp.os.minix] Named pipes in O_NONBLOCK mode bug

regan@jacobs.CS.ORST.EDU (Dave Regan) (07/20/90)

I am working on an application using named pipes in O_NONBLOCK mode under
Minix 1.5.10.  It appears that there is a bug in fs/open.c in function
pipe_open.  If in O_NONBLOCK mode, the function will return with either
ENXIO or OK, but will not set the rip->i_pipe field to I_PIPE at the
end of the function.

This appears to have rather nasty properties throughout the rest of
the code regarding the use of this pipe.

The following is my change to fix this problem.

A warning to other people converting programs using named pipes to
run under Minix:  Remember the mknod function requires an extra parameter.
After I found why the program was misbehaving, I remembered this.

			Dave Regan
			regan@jacobs.cs.orst.edu
			
---------------------------------------------------------------------------
*** open.c.orig	Thu Jun 28 21:49:10 1990
--- open.c	Wed Jul 18 22:16:03 1990
***************
*** 258,273 ****
  /*  This function is called from do_creat and do_open, it checks if
   *  there is at least one reader/writer pair for the pipe, if not
   *  it suspends the caller, otherwise it revives all other blocked
   *  processes hanging on the pipe.
   */
  
    if (find_filp(rip, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { 
! 	if (oflags & O_NONBLOCK) return(bits & W_BIT ? ENXIO : OK);
! 	suspend(XOPEN); /* suspend caller */
    } else if (susp_count > 0) {/* revive blocked processes */
  	release(rip, OPEN, susp_count);
  	release(rip, CREAT, susp_count);
    }
    rip->i_pipe = I_PIPE; 
  
    return OK ;
--- 258,276 ----
  /*  This function is called from do_creat and do_open, it checks if
   *  there is at least one reader/writer pair for the pipe, if not
   *  it suspends the caller, otherwise it revives all other blocked
   *  processes hanging on the pipe.
   */
  
    if (find_filp(rip, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { 
! 	if (oflags & O_NONBLOCK) {
! 		if (bits & W_BIT)
! 			return ENXIO ;
! 	} else
! 		suspend(XOPEN); /* suspend caller */
    } else if (susp_count > 0) {/* revive blocked processes */
  	release(rip, OPEN, susp_count);
  	release(rip, CREAT, susp_count);
    }
    rip->i_pipe = I_PIPE; 
  
    return OK ;