[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] cygwin+bash: bash reorders script output bug identified/fixed

From: Manfred Spraul
Subject: [PATCH] cygwin+bash: bash reorders script output bug identified/fixed
Date: Tue, 06 Aug 2002 09:06:52 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.0) Gecko/20020530


I've figured out why bash reorders output from my shell script. I've
attached a new, simpler script to reproduce the bug
Just run


If it fails, then lines in output.txt are reordered
(i.e. script output something).
Please retry a few times, it's not 100% reproducable.

* It's a bash bug, not a cygwin bug.
* defining RECYCLES_PIDS in execute_cmd.c solves the problem.
* RECYCLES_PID is intended for LynxOs, which recycles pids
      quickly according to a comment in execute_cmd.c
* All OS are potentially affected, bash basically assumes
      that 2 pid values are never identical.

It seems that there are 2 possible solutions:
A) enable RECYCLES_PID in bash.
      * I'd propose that, minimal patch attached.
B) work around the bash bug in cygwin.
      fork.cc already contains a special function that prevents 2
          consecutive fork() calls from reusing the same pid:

But it doesn't work in this context:

When bash executes a command, it sometimes creates a subprocess.
make_child saves the new pid in a global variable (last_made_pid).
execute_command_internal() calls execute_simple_command() and checks
if last_made_pid has changed during the call. If last_made_pid has not
changed (command was a builtin, handled without fork()), then wait_for()
is not called by execute_command_internal(), to prevent bash from

I.e. if the same pid is used for 2 consecutive command subprocesses,
bash fails, because it thinks the command was a builtin and doesn't wait
until the external process exits.

My probem is caused by process_substitute: The function handles command
substitution, and that function saves & restores last_made_pid.

Thus the same pid value must not be used for 2 consecutive _command_
subprocesses, which is different from 2 consecutive fork() calls.

I don't see how fork.cc could work around that bash bug. I'd propose the
attached patch, that enables RECYCLES_PIDS for cygwin.

Note: I've manually edited both configure.in and configure, because I
don't have autoconf installed. Please test before applying the patch.
Obviously I'd prefer if RECYCLES_PIDS is unconditionally enabled in
all OS.

<<<<<< bugbash output:

Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: cygwin
Compiler: i686-pc-cygwin-gcc
Compilation CFLAGS:  -DPROGRAM='bash.exe' -DCONF_HOSTTYPE='i686'
-DCONF_OSTYPE='cygwin' -DCONF_MACHTYPE='i686-pc-cygwin'
-DCONF_VENDOR='pc' -DSHELL -DHAVE_CONFIG_H  -I.  -I../bash-2.05b
-I../bash-2.05b/include -I../bash-2.05b/lib -g -O2
uname output: CYGWIN_NT-5.0 AB 1.3.12(0.54/3/2) 2002-07-03 16:42 i686
Machine Type: i686-pc-cygwin

Bash Version: 2.05b
Patch Level: 0
Release Status: release

cygwin version: 1.3.12-1

# the comments explain what's needed to trigger the bug
fnc() {
# e.g. process id 1000
        while [ $n -lt 50 ];do 
                rm -f m-$n.txt
                # subprocess created for rm.
                # process id 1001, saved in last_made_pid.
                echo "YYY  $n" > lfile.txt
                echo "W    $n"
                for i in 0 1 2 3 4 5 6 7 8 9 10;do 
                        mu=`echo $n $i | gawk '{printf("%f\n",$1+$2);}'`
                        # several subprocesses created by
                        # process_substitute.
                        # consecutive pid values are never identical,
                        # bug process_substitute always restores 
                        # last_made_pid to 1001.
                        echo "$mu" >> m-$n.txt
                echo "XX   $n"
                cat lfile.txt
                # subprocess created, pid 1001.
                # result: execute_command_internal thinks that it's
                # a builtin and doesn't wait until cat exits.
                echo "ZZZZ $n"
                # echo prints "ZZZZ $n"
                # now cat runs, and outputs YYY --> YYY after ZZZZ
                rm -f m-$n.txt

rm -f m-*.txt
fnc > output.txt
rm lfile.txt
# now check if the output file is correct
gawk ' {i++} /W/{if (i%4 != 1) printf("%s\n",$0);} /X/{if (i%4 != 2) 
printf("%s\n",$0);} /Y/{if (i%4 != 3) printf("%s\n",$0);} /Z/{if (i%4 != 0) 
printf("%s\n",$0);}' < output.txt

Attachment: patch-bash
Description: application/java-applet

reply via email to

[Prev in Thread] Current Thread [Next in Thread]