0.10.0 — the exec search, and the family of answers that were not true
openkal-linux#13, fifth round.
A consumer measured that execvp could not get past the first PATH entry that
missed — one libc path accounting for nine of their nineteen failures, plus
four sections silently skipped because bwrap, installed at /usr/bin/bwrap,
was reported as not installed. That is fixed, and reading it out found six more
of the same family.
⭐⭐ What they have in common
Every probe in this repository asked whether an operation worked. None asked
whether an answer was true. OPENKAL_MUSL_TRACE=enosys reports what reaches
the default arm, and not one of these reaches it — they are operations that are
present and answer wrongly. examples/surface is new, and is the probe that asks
the other question.
⚠️ ⚠️ The heaviest one was not in the report
fcntl(F_SETLK), F_SETLKW and F_GETLK answered 0 and did nothing. Measured
against the host: two programs took one exclusive lock and both were told they
had it. F_GETLK pointed the other way — it left the caller's word untouched,
which reads as "somebody holds this", for ever, so a loop waiting for a lock
never left it. All three now report ENOSYS.
⭐ That refusal is temporary in a way the permission one is not: every
environment beneath openkal can lock a byte range, and what is missing is a word
in the specification — asked for as mcpplibs/openkal#22.
Answered
execvereturns when the program cannot be started, soexecvpcan search
a PATH.posix_spawnreportsENOENT/EACCESinstead of success.posix_spawnpsearches PATH at all — musl's source is replaced, the tenth.getppidno longer hands back -38 as an identifier (the defectgetpgrp
had one release earlier, three lines away, and that was not looked for).- A copy made by
forknames itself instead of reporting its parent. setpgid(0,0)→0andsetsid()→EPERM, the failure POSIX writes down.
Every daemonising library handlesEPERM; none handlesENOSYS.sigaltstackrefuses instead of reporting an installation it did not perform.sysconf(_SC_OPEN_MAX)answers the bound this library sets, not0.- A directory's modification time can be set where the implementation can
open a directory (Linux, macOS; not Windows). Reading it was never broken — the
consumer reported it as a read failure because libc++ gives both overloads of
last_write_timeone name.
⚠️ Not answered, and now recorded
kill does not reach a program started by fork + execve — it reaches the
copy that is waiting for it. Measured with the host as control: identical status
words, opposite outcomes. Use posix_spawn, system or popen where you need
to stop what you started. Asked for as mcpplibs/openkal#23.
README.md and musl/PATCHES.md claimed a caller cannot distinguish
execve-as-spawn+wait from a real replacement. That claim was false, and is what
kept anyone from looking. Both now list the three known differences.
Also recorded: access(X_OK) answers yes for anything that exists; descriptors
above 2 do not cross into a started program; sched_getaffinity is absent so
hardware_concurrency() answers 1 silently; statvfs, link, mkfifo and
socketpair have no operation beneath.
Criteria
examples/surface fails eleven of its observations on 0.9.0 and none here.
examples/subprocess gains the exec search and the identity, and on 0.9.0 it
does not merely fail — it stops, at the execve observation, which is the
defect itself.