Subject: Re: [PATCH v3] tap: new `--stderr-prefix' option to prefix test script's stderr

From: Richard Hansen <[email-masked]>
Date: Thu, 20 Feb 2025 01:15:49 -0500

On 2/19/25 12:47, Karl Berry wrote:
> However ... when I ran make check with the changes installed, the
> tap-merge-stdout-stderr test failed. Did it succeed for you? Before I
> delved into it, thought I'd check back.

Doh!  There's a race condition and no portable (POSIX) way to fix it, I 
think.  The proposed change spawns an asynchronous subshell (a pipeline 
stage) to read stderr, prefix each line, and write the results to 
stdout.  That subshell is a separate process/thread that races with the 
direct writes to stdout.

The only race-free* fix is to use a select or poll loop to read from 
both stderr and stdout simultaneously from a single thread. 
Unfortunately, there is no portable way (that I know of) to use those 
system interfaces from a shell script.  Perl, Python, etc. can do it, 
but those add a new dependency.  It's not practical to ship a C file and 
compile that when the user runs the tests (right?).

I can reduce the severity of the out-of-order writes by (a) not piping 
stderr through the prefixing function when the prefix is the empty 
string, and (b) avoiding stdout buffering when stderr is prefixed. 
These changes might provide good enough results for most users.  Users 
that require stronger guarantees can wrap their test program in a custom 
helper utility rather than rely on Automake's TAP driver to do the 
prefixing and merging.

Thoughts and suggestions would be appreciated.

-Richard

*Even a select/poll loop wouldn't be completely race-free: if the test 
process writes to both stdout and stderr while a previous write is still 
being processed then the next loop iteration won't know whether the 
stdout or the stderr write happened first.