From owner-freebsd-current Wed Oct 14 07:25:31 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id HAA28641 for freebsd-current-outgoing; Wed, 14 Oct 1998 07:25:31 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from ganymede.or.intel.com (ganymede.or.intel.com [134.134.248.3]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id HAA28636 for ; Wed, 14 Oct 1998 07:25:30 -0700 (PDT) (envelope-from wscott@ichips.intel.com) Received: from ichips-ra.pdx.intel.com (ichips-ra.pdx.intel.com [137.102.192.31]) by ganymede.or.intel.com (8.8.6/8.8.5) with ESMTP id OAA17572 for ; Wed, 14 Oct 1998 14:25:15 GMT Received: from pdxcs565.pdx.intel.com (pdxcs565.pdx.intel.com [137.102.209.215]) by ichips-ra.pdx.intel.com (8.8.8/8.8.7) with ESMTP id HAA12203 for ; Wed, 14 Oct 1998 07:25:14 -0700 (PDT) Received: from ichips.intel.com by pdxcs565.pdx.intel.com (8.8.8/WW2.2 (Ronler Acres)) id HAA26802; Wed, 14 Oct 1998 07:25:14 -0700 Message-Id: <199810141425.HAA26802@pdxcs565.pdx.intel.com> To: current@FreeBSD.ORG Subject: simple popen() bug and solution (PATCH) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Date: Wed, 14 Oct 1998 07:25:14 -0700 From: Wayne Scott Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG This is a restatement of PR misc/7810. Since that PR is making NO progress I thought I would restate the problem in terms everyone can understand. The Problem ----------- The following program hangs on all current versions of FreeBSD, but works on Linux, AIX, and HPUX. #include #include main() { FILE *file1; FILE *file2; file1 = popen("gzip > file1.gz", "w"); file2 = popen("gzip > file2.gz", "w"); fprintf(file1, "This is a test\n"); fprintf(file2, "This is also a test\n"); pclose(file1); pclose(file2); } The Cause --------- When popen exec's the second gzip process, that process inherits the open filehandle 'file1'. When 'pclose(file1)' is executed the first gzip does not exit because the second gzip is still holding an open handle for its input. The Workaround -------------- If you reverse the order of the 'pclose()' calls then the program works correctly, but this is not possible in the big program I am really trying to get work. The other Workaround -------------------- If you set the 'close_on_exec' flag on the 'file1' then the second gzip will not inheret open file handle. ex. fcntl(fileno(file1), F_SETFD, 1) This works, but is changes the semantics of popen(). What POSIX says --------------- /* Posix.2: "popen() shall ensure that any streams from previous popen() calls that remain open in the parent process are closed in the new child process." */ The Solution ------------ popen() already maintains a list of filehandles that have be previously returned. We just need to walk that list and close all the files. No need to deallocate the list because we are just about the exec() anyway. Index: popen.c =================================================================== RCS file: /home/ncvs/src/lib/libc/gen/popen.c,v retrieving revision 1.9 diff -u -r1.9 popen.c --- popen.c 1997/04/22 09:44:06 1.9 +++ popen.c 1998/09/02 18:47:49 @@ -62,6 +62,7 @@ struct pid *cur; FILE *iop; int pdes[2], pid, twoway; + struct pid *p; /* * Lite2 introduced two-way popen() pipes using socketpair(). @@ -115,6 +116,9 @@ (void)close(pdes[0]); } (void)close(pdes[1]); + } + for (p = pidlist; p; p = p->next) { + close(fileno(p->fp)); } execl(_PATH_BSHELL, "sh", "-c", command, NULL); I would love to have this fixed in the 3.0 release of FreeBSD. Note I sent the PR with the patch in plenty of time... Wayne Scott MD6 Architecture - Intel Corp. wscott@ichips.intel.com Work #: (503) 613-5063 Disclaimer: All views expressed are my own opinions, and not necessarily those of Intel Corporation. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message