Subject: lib/2575: task will hang when calling pclose
To: None <gnats-bugs@NetBSD.ORG>
From: Clifford Wright <cliff@wport.com>
List: netbsd-bugs
Date: 06/26/1996 21:24:49
>Number:         2575
>Category:       lib
>Synopsis:       task will hang when calling pclose
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    lib-bug-people (Library Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 27 00:50:02 1996
>Last-Modified:
>Originator:     Clifford Wright
>Organization:
	
>Release:        1.1
>Environment:
	
	All
System: NetBSD vixen 1.1 NetBSD 1.1 (VIXEN) #28: Tue Jun 25 01:40:06 PDT 1996 cliff@vixen:/usr/src/sys/arch/i386/compile/VIXEN i386


>Description:
	
	When running the WWW browser Grail from CNRI and doing multiple jpeg
	image loads the browser would hang. Investigation showed this occured
	after multiple popen's had been called and a pclose was issued on the
	first popen stream.
>How-To-Repeat:
	
>Fix:
	
	The popen library routine should have closed all file descriptors except
	the input or output stream after the fork. Otherwise the reference
	count on the stream file descriptor will be incremented when other
	popen calls are made, and a complete close can not occur on the first
	stream file descriptor when pclose is called until the later streams all
	close. Since pclose does a wait forever on a complete close of the
	fisrt stream, the close on the later streams never occurs, and thus
	the task hangs.
	The diff against base NetBSD 1.1 follows.

*** popen.c.orig	Fri Oct 13 17:47:41 1995
--- popen.c	Wed Jun 26 21:22:16 1996
***************
*** 68,74 ****
  {
  	struct pid *cur;
  	FILE *iop;
! 	int pdes[2], pid;
  
  	if (*type != 'r' && *type != 'w' || type[1]) {
  		errno = EINVAL;
--- 68,74 ----
  {
  	struct pid *cur;
  	FILE *iop;
! 	int pdes[2], pid, fd;
  
  	if (*type != 'r' && *type != 'w' || type[1]) {
  		errno = EINVAL;
***************
*** 94,108 ****
  		if (*type == 'r') {
  			if (pdes[1] != STDOUT_FILENO) {
  				(void)dup2(pdes[1], STDOUT_FILENO);
- 				(void)close(pdes[1]);
  			}
! 			(void) close(pdes[0]);
  		} else {
  			if (pdes[0] != STDIN_FILENO) {
  				(void)dup2(pdes[0], STDIN_FILENO);
- 				(void)close(pdes[0]);
  			}
! 			(void)close(pdes[1]);
  		}
  		execl(_PATH_BSHELL, "sh", "-c", program, NULL);
  		_exit(127);
--- 94,112 ----
  		if (*type == 'r') {
  			if (pdes[1] != STDOUT_FILENO) {
  				(void)dup2(pdes[1], STDOUT_FILENO);
  			}
! 			for(fd = 0; fd < NOFILE; fd++) {
!                                 if(fd != STDOUT_FILENO)
!                                         (void)close(fd);
!                         }
  		} else {
  			if (pdes[0] != STDIN_FILENO) {
  				(void)dup2(pdes[0], STDIN_FILENO);
  			}
! 			for(fd = 0; fd < NOFILE; fd++) {
!                                 if(fd != STDIN_FILENO)
!                                         (void)close(fd);
!                         }
  		}
  		execl(_PATH_BSHELL, "sh", "-c", program, NULL);
  		_exit(127);
>Audit-Trail:
>Unformatted: