On Mon, Apr 8, 2024 at 3:50 PM Chet Ramey <chet.ra...@case.edu> wrote: > > On 4/4/24 7:23 PM, Martin D Kealey wrote: > > I'm somewhat uneasy about having coprocs inaccessible to each other. > > I can foresee reasonable cases where I'd want a coproc to utilize one or > > more other coprocs. > > That's not the intended purpose, so I don't think not fixing a bug to > accommodate some future hypothetical use case is a good idea. That's > why there's a warning message when you try to use more than one coproc -- > the shell doesn't keep track of more than one.
That use case is always going to be hypothetical if the support for it isn't really there, though, isn't it? > If you want two processes to communicate (really three), you might want > to build with the multiple coproc support and use the shell as the > arbiter. If you've written a script for other people than just yourself, expecting all of them to build their own bash install with a non-default preprocessor directive is pretty unreasonable. The part that I've been missing this whole time is that using exec with the fds provided by the coproc keyword is actually a complete solution for my use case, if I'm willing to close all the resultant fds myself in background processes where I don't want them to go. Which I am. $ coproc CAT1 { cat; } [1] 1769 $ exec {CAT1_2[0]}<&"${CAT1[0]}" {CAT1_2[1]}>&"${CAT1[1]}" {CAT1[0]}<&- {CAT1[1]}>&- $ declare -p CAT1 CAT1_2 declare -a CAT1=([0]="-1" [1]="-1") declare -a CAT1_2=([0]="10" [1]="11") $ coproc CAT2 { exec {CAT1_2[0]}<&- {CAT1_2[1]}>&-; cat; } [2] 1771 $ exec {CAT2_2[0]}<&"${CAT2[0]}" {CAT2_2[1]}>&"${CAT2[1]}" {CAT2[0]}<&- {CAT2[1]}>&- $ declare -p CAT2 CAT2_2 declare -a CAT2=([0]="-1" [1]="-1") declare -a CAT2_2=([0]="12" [1]="13") $ printf 'dog\ncat\nrabbit\ntortoise\n' >&"${CAT1_2[1]}" $ IFS='' read -r -u "${CAT1_2[0]}" line; printf '%s\n' "${?}:${line}" 0:dog $ exec {CAT1_2[1]}>&- $ IFS='' read -r -u "${CAT1_2[0]}" line; printf '%s\n' "${?}:${line}" 0:cat [1]- Done coproc CAT1 { cat; } $ IFS='' read -r -u "${CAT1_2[0]}" line; printf '%s\n' "${?}:${line}" 0:rabbit $ IFS='' read -r -u "${CAT1_2[0]}" line; printf '%s\n' "${?}:${line}" 0:tortoise $ IFS='' read -r -u "${CAT1_2[0]}" line; printf '%s\n' "${?}:${line}" 1: $ exec {CAT1_2[0]}<&- {CAT2_2[0]}<&- {CAT2_2[1]}>&- $ [2]+ Done No warning message when creating the CAT2 coproc. I swear, I was so close to getting this figured out three years ago, unless the behavior when a coproc still exists only because other non-coproc fds are pointing to it has changed since whatever version of bash I was testing in at the time. I am completely satisfied with this solution. The trial and error aspect to figuring this kind of stuff out is really frustrating. Maybe I'll take some time and write a Wooledge Wiki article on this at some point, if there isn't one already. Whether the coproc fds should be automatically kept out of most kinds of subshells, like it is now; or out of more kinds than currently; is kind of beside the point to me now. But, having a builtin to ensure the same behavior is applied to any arbitrary fd might be useful to people, especially if those fds get removed from process substitutions as well. If the code for coproc fds gets applied to these fds, then you've got more chances to see that the logic actually works correctly, if nothing else.