ma lz <[email protected]> writes:
> In certain environments (e.g., CentOS 7 host with Docker container running 
> Euler 24.03, older kernel), popen() internally first tries clone3, which 
> fails with ENOSYS (38), then falls back to traditional clone and succeeds. 
> However, the errno value from the failed clone3 attempt (38) is not cleared, 
> so after a successful popen(), errno remains 38.

Sure.

> If a caller (incorrectly) checks errno even when popen() succeeds, they might 
> see errno == ENOSYS and mistakenly believe an error occurred, even though the 
> command executed successfully.

That would be a a bug in that caller (and I don't see any such
caller).  It is *extremely* common for system functions to trash errno
in non-failure paths.  That variable is only promised to be meaningful
after a failure return.

The point of the errno = 0 step in popen_check() is so that we don't
print an unrelated error code if popen fails without setting errno.
POSIX doesn't require it to set errno, oddly enough:

    Upon successful completion, popen() shall return a pointer to an
    open stream that can be used to read or write to the
    pipe. Otherwise, it shall return a null pointer and may set errno
    to indicate the error.

> Proposed Fix
> Move errno = 0 to the success path, so errno is only cleared when popen() 
> actually succeeds:

This is based on a complete misunderstanding of what that step is for.
It would break the case we're protecting against without fixing
anything.

                        regards, tom lane


Reply via email to