bug-bash
[Top][All Lists]
Advanced

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

wait fails to grab exit codes with multiple process substitutions


From: leo . dalecki
Subject: wait fails to grab exit codes with multiple process substitutions
Date: Sat, 14 Sep 2019 12:29:26 +0200 (CEST)

From: leo.dalecki@ntymail.com
To: bug-bash@gnu.org
Subject: wait fails to grab exit codes with multiple process substitutions

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -g -O2 -fdebug-prefix-map=/build/bash-2bxm7h/bash-5.0=. 
-fstack-protector-strong -Wformat -Werror=format-security -Wall 
-Wno-parentheses -Wno-format-security
uname output: Linux debian 4.19.0-5-amd64 #1 SMP Debian 4.19.37-5+deb10u2 
(2019-08-08) x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 5.0
Patch Level: 3
Release Status: release

Description:
        Hi,

        I was trying to write a script that could run an arbitrary amount of 
asynchronous commands, and then as soon as one finishes, perform actions
        according to its exit code and output. 

        I attempted to do this by using process substitution and the wait 
command. But wait's ability to retrieve the exit code of a finished process 
        that is a current shell's children seems inconsistent.

        The script starts ten asynchronous commands by redirecting a process 
substitution's file descriptor to one of the current shell using exec.
        The script then uses wait with the process IDs of the asynchronous 
tasks to retrieve their exit codes.

        wait fails on nine of the ten tasks, giving the error "wait: pid X is 
not a child of this shell". But weirdly enough, it succeeds when retrieving 
        the exit code of the last asynchronous task to be run.

        The exact script I use is included in Repeat-By section, as a way to 
trigger the bug.

        Thank you and have a nice day.

Repeat-By:
        The following script reproduces the behavior I described in the 
Description section:

        
        #!/bin/bash
        
        # bg.sh
        
        # Executing commands asynchronously, retrieving their exit codes and 
outputs upon completion.
        
        asynch_cmds=
        
        echo -e "Asynchronous commands:\nPID    FD"
        
        for i in {1..10}; do
                exec {fd}< <(sleep $(( i * 2 )) && echo $RANDOM && exit $i) # 
Dummy asynchronous task, standard output's stream is redirected to the current 
shell
                asynch_cmds+="$!:$fd " # Append the task's PID and FD to the 
list of running tasks
        
                echo "$!        $fd"
        done
        
        echo -e "\nExit codes and outputs:\nPID FD      EXIT    OUTPUT"
        
        while [[ ${#asynch_cmds} -gt 0 ]]; do # While the list of running tasks 
isn't empty
        
                for asynch_cmd in $asynch_cmds; do # For each task in the list
        
                        pid=${asynch_cmd%:*} # Task's PID
                        fd=${asynch_cmd#*:} # Task's FD
        
                        if ! kill -0 $pid 2>/dev/null; then # If the task ended
        
                                wait $pid # Retrieving the task's exit code
                                echo -n "$pid   $fd     $?      "
        
                                cat <&$fd # Retrieving the task's output
        
                                asynch_cmds=${asynch_cmds/$asynch_cmd /} # 
Removing the task from the list
                        fi
                done
        done


        By running this script, you will see that wait gives the error I 
described. And also that the tenth task (with exit code 10) doesn't trigger the 
wait error.



reply via email to

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