ma lz <ma100@hotmail.com> writes:
> In certain environments (e.g., CentOS 7 host with Docker container running Euler 24.03, older kernel), popen()
internallyfirst tries clone3, which fails with ENOSYS (38), then falls back to traditional clone and succeeds. However,
theerrno 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
believean 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