bug-bash
[Top][All Lists]
Advanced

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

Fixing coproc race condition bug


From: Jim Avera
Subject: Fixing coproc race condition bug
Date: Sun, 24 Oct 2021 13:44:11 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0

#!/usr/bin/env bash
set -e -u

coproc date

sleep 1

# In bash 5.0.17, this aborts with "COPROC[0]: unbound variable"
# if the coproc exits before the main process gets here.
read -u ${COPROC[0]} line

# Discussion:
#
# To prevent this race condition, Bash must not close the coproc output pipe
# when the coprocess exits, but keep it open until the main process has had
# a chance to read buffered data.
#
# However bash must prevent unbounded leaking file descriptors/pipes
# -- see ideas below.
#
# (The coproc *input* pipe can be closed when the coprocess exits because
# it can no longer be used -- a SIGPIPE error would occur if written to.)
#
# SUGGESTED STRATEGY:
#
#   Close the coproc output pipe after the main process reads EOF from it.
#     --This handles all cases where the coproc writes but does not read.
#
#   Close both pipes before executing another 'coproc' command with the
#     same effective NAME, i.e. which will overwrite the "COPROC" array.
#     --This prevents leaking fds in loops or repetitive code.
#
#   Close both pipes and undef COPROC if the main process reaps a coproc
#     child with 'wait'.
#     --This allows scripts to explicitly release coproc resources
#
# The above is probably good enough.
#
# Another tweak would be define a "no-op" coproc command to be a special
# case which does not create new pipes, but only closes any previous pipes
# associated with the same NAME (as described above).
# e.g.
#    coproc;           # implied NAME is "COPROC"
#    coproc NAME {};   # explicit NAME
#
# However this would be unnecessary (i.e. redundant) if doing 'wait' on
# a coproc child implicitly closes it's pipes.
#
# Note: Ignore errors when closing pipes, as the user might have manually closed
# the fds using 'exec {varname}>&-' or similar.
#
#(END)




reply via email to

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