[Top][All Lists]

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

Re: process substitution error handling

From: Eli Schwartz
Subject: Re: process substitution error handling
Date: Thu, 6 Aug 2020 12:21:34 -0400

On 8/6/20 11:31 AM, Jason A. Donenfeld wrote:
> That doesn't always work:
> set -e
> while read -r line; do
>        echo "$line" &
> done < <(echo 1; sleep 1; echo 2; sleep 1; exit 77)
> sleep 1
> wait $!
> echo done

So instead of your contrived case, write it properly. Check the process
substitution first, and make sure as a bonus you don't run anything if
if it failed:

set -e
mapfile -t lines < <(echo 1; sleep 1; echo 2; sleep 1; exit 77)
wait $!

for line in "${lines[@]}"; do
       echo "$line" &
sleep 1
wait $!
echo done

(And in bash 5.1 you can remember each &'ed command to wait on later.)

> Either way, tagging on `wait $!` everywhere, and hoping it works like
> I want feels pretty flimsy. Are you sure you're opposed to set -o
> procsuberr that would do the right thing for most common use cases?

You're asking to add broken behavior which does the wrong thing in
bizarre, outrageous ways in many cases.

Your rationale is it works in your specific case, and you have a
mysterious aversion to wait $! which you haven't explained. (Why is it
flimsy? It performs exactly as documented.)

I think the problem here is twofold:

You have an emotional attachment to errexit and you think it solves
problems, so you want to turn everything into it.

Ultimately, you really don't have issues with "flimsy" anything, but you
want bash to be a different language, one with a formal exception model,
strong types, and possibly objects. Such a language would then react to
*programmer errors* by failing to compile, or dumping a traceback of the
call site, and could be used as a beginner-friendly language that
doesn't surprise the newbies.

There are a number of good languages like that. Shell isn't one of them.
Sometimes you need to understand how edge cases work.

Nevertheless, there are ways to code robustly in it. In another
language, you'd run forked commands upfront and save their results to
some sort of object or variable, and only then process it (after
checking the return code or using a function that automatically raises
exceptions on failure).
You can do that in bash too, as I demonstrated with mapfile and wait $!

It isn't really a terrible disadvantage that you need more characters to
type out your intent. Most particularly when your intent is "I want this
command to run async, but I also want it to exit the script at XXX
location if previous aysnc commands have failed". You cannot really get
around explicitly tagging the place where you want to raise errors.
Using an RNG to randomly raise the error automatically at unpredictable
locations isn't a valuable feature to add.

Eli Schwartz
Arch Linux Bug Wrangler and Trusted User

Attachment: signature.asc
Description: OpenPGP digital signature

reply via email to

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