#!/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)