Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Date: Sat, 18 Oct 2003 01:58:36 -0400 From: Christopher Faylor To: cygwin AT cygwin DOT com Subject: Re: cygpath hangings: A fix - bash patch enclosed -- bash maintainer please note! Message-ID: <20031018055836.GA28155@redhat.com> Reply-To: cygwin AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com References: <20031015184328 DOT GD28402 AT redhat DOT com> <20031015203012 DOT GA9255 AT redhat DOT com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20031015203012.GA9255@redhat.com> User-Agent: Mutt/1.4.1i Note-from-DJ: This may be spam On Wed, Oct 15, 2003 at 04:30:12PM -0400, Christopher Faylor wrote: >I just managed to duplicate the problem on my system at work. > >Stay tuned. I managed to duplicate it at home by booting into W2K, too. That meant I didn't have to feel guilty about working on this at work. :-) This should fix the problem. Bash wasn't closing the read end of a pipe in some situations. I'm not sure why that would cause some programs to hang but the following patch fixes the problem. I think it provides more robust code than what was in bash previously, too. Ronald, if you agree with this patch, could you release a new version of bash, ASAP? If you don't agree with the patch, then please let me (aka the cygwin list) know soon since I'm going to be submitting it upstream ASAP. cgf 2003-10-18 Christopher Faylor * subst.c (command_substitute): Guard against opening a pipe handle in stdin/stdout/stderr since they may be closed and keeping the pipe handle open in a subprocess will cause hangs. --- subst.c.orig 2003-10-15 15:09:01.000000000 -0400 +++ subst.c 2003-10-18 01:47:49.737056307 -0400 @@ -3716,6 +3716,7 @@ command_substitute (string, quoted) pid_t pid, old_pid, old_pipeline_pgrp; char *istring; int result, fildes[2], function_value; + int i, closeit[3]; istring = (char *)NULL; @@ -3742,6 +3743,16 @@ command_substitute (string, quoted) if (subst_assign_varlist == 0 || garglist == 0) maybe_make_export_env (); /* XXX */ + + for (i = 0; i <= 2; i++) + if (fcntl (i, F_GETFD, &result) != -1) + closeit[i] = 0; + else + { + open ("/dev/null", O_RDONLY); + closeit[i] = 1; + } + /* Pipe the output of executing STRING into the current shell. */ if (pipe (fildes) < 0) { @@ -3749,6 +3760,10 @@ command_substitute (string, quoted) goto error_exit; } + for (i = 0; i <= 2; i++) + if (closeit[i]) + close (i); + old_pid = last_made_pid; #if defined (JOB_CONTROL) old_pipeline_pgrp = pipeline_pgrp; @@ -3793,21 +3808,8 @@ command_substitute (string, quoted) exit (EXECUTION_FAILURE); } - /* If standard output is closed in the parent shell - (such as after `exec >&-'), file descriptor 1 will be - the lowest available file descriptor, and end up in - fildes[0]. This can happen for stdin and stderr as well, - but stdout is more important -- it will cause no output - to be generated from this command. */ - if ((fildes[1] != fileno (stdin)) && - (fildes[1] != fileno (stdout)) && - (fildes[1] != fileno (stderr))) - close (fildes[1]); - - if ((fildes[0] != fileno (stdin)) && - (fildes[0] != fileno (stdout)) && - (fildes[0] != fileno (stderr))) - close (fildes[0]); + close (fildes[1]); + close (fildes[0]); /* The currently executing shell is not interactive. */ interactive = 0; -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/