Commit 4e7f0ac
authored
0.8.0 --- truncate(2), and the backends that fixed the EAGAIN this port reported (#20)
* truncate(2) had no case, so resize_file reported ENOSYS for every path
Only `ftruncate' was answered. The two are not interchangeable to a caller
holding a name and no open file, which is every caller of
`std::filesystem::resize_file': libc++ expresses it as
`detail::truncate(p.c_str(), size)'. Reported in openkal-linux#13, where
operation 76 appears in the trace of an ordinary run.
Composed exactly as `SYS_utimensat' beside it is: resolve the name, open the
file for reading and writing, act, release. Opened for both because openkal
decides at the point of opening what may afterwards be done with a file, and the
divergence that produces from POSIX -- which asks for write permission and not
for read -- is the one already recorded there.
--- and two observations about a directory's modification time ---------------
`examples/posix' gains four observations. Two are the operation above, taken
with the descriptor already closed so that nothing can reach the one that
already worked:
ok: the length is set by name
ok: the length set by name is the length reported
and with the case removed again they are
FAIL: the length is set by name (errno=38)
FAIL: the length set by name is the length reported (errno=38)
The other two record an asymmetry that a consumer read the wrong way round, and
they are here because the C++ library above gives the two overloads one name.
`std::filesystem::last_write_time' throws `filesystem error: in last_write_time'
whether it was reading or writing, so a caller cannot tell from the message
which failed. Measured:
ok: a directory reports its modification time
ok: setting a directory's modification time is refused, as EISDIR
Reading resolves a directory perfectly well. Setting does not, because
`kal_fs_set_modified' takes a `kal_file' and openkal has no form of it that takes
a directory or a name, so this port opens the name as a file. A caller holding a
lock directory reads its timestamp to decide staleness and writes it to refresh
the lock, and only the second fails; openkal-linux#13 reported it as the first.
README.md carries the row. The refusal is asserted rather than merely not
exercised, so that the row is contradicted if openkal ever gains the operation.
Measured: 47 observations, 0 failures, and `OPENKAL_MUSL_TRACE=enosys' over the
whole probe now prints nothing at all.
* 0.8.0 --- repin the two backends, and record round four of openkal-linux#13
`openkal-linux 0.7.1` and `openkal-macos 0.6.1` correct `kal_timeout_read` and
`kal_timeout_write`, which decoded a borrowed `kal_stream` handle with the
decoder for an owned one and so waited upon the descriptor below the one they
transferred upon.
THIS PORT IS WHERE THAT DEFECT WAS OBSERVED AND IS NOT WHERE IT WAS. libc++
opens a copy's source with `O_NONBLOCK`, `do_read` routes that through
`okm_timed_read`, and `SYS_copy_file_range` is a `do_read`/`do_write` loop, so
every byte of a file copy passed through a wait upon the wrong descriptor.
`EAGAIN` is not in libc++'s fallback list, so `std::filesystem::copy_file`
reported `Resource temporarily unavailable` for two ordinary files. Nothing in
this port needed to change: the route through `O_NONBLOCK` was correct and what
it reached was not.
`.agents/docs/2026-08-30-issue13-round-four-timeout-truncate-and-provenance.md`
records the round: what the report contained, what it did not, and the two items
that remain open.
Two of its findings are worth naming here because they change what the next
round should do.
FIRST, THE CRASH THE REPORT CALLS UNFIXED WAS FIXED IN 0.7.0, AND THE BUILD THAT
WAS MEASURED DID NOT CONTAIN IT. The reported `OPENKAL_MUSL_TRACE` list names
operations 88 and 324. Neither can be printed by 0.7.0: `symlink` and
`symlinkat` have cases, `membarrier` has a case of its own whose stated purpose
is that the trace not report it, and `trace_absent` is called from the default
arm and nowhere else. Both numbers are defined for that architecture, so both
cases are live. The measured library was 0.6.0, and since
openkal-llvm-runtime 0.4.0 requires 0.7.0, the runtime was 0.3.1.
SECOND, AND IT IS WHY THE FIRST COULD HAPPEN: A PROGRAM BUILT ON THIS PORT
CANNOT STATE WHICH VERSION OF IT IT HOLDS. The only thing resembling a version a
program can read is `SYS_uname`'s release field, which is the string literal
"0.5.0" and has never moved. A consumer who checks it is told a version, and the
version is wrong. §7 of the document proposes deriving that field from the
package version and having the trace name the version before anything else; it
is not done here, because it is a change to what a program observes and belongs
in a release of its own rather than beside a repin.
* ci: the fetch of the installer retries transport failures, which --retry does not cover
One row of this branch's first run reported
curl: (35) Recv failure: Connection reset by peer
##[error]Process completed with exit code 35
thirteen seconds in, before anything was built. `--retry` covers a transient
HTTP status and a timeout and does not cover a failure of the transport;
`--retry-all-errors` is the flag that does.
The same unprotected fetch is in openkal-linux, openkal-macos, openkal and
openkal-llvm-runtime, eight occurrences in total. They are left for changes of
their own rather than folded in here.
* The new observation asserted a value that belongs to the backend, not to this port
The Windows row of the matrix answered
FAIL: setting a directory's modification time is refused, as EISDIR (errno=13)
and it was right to. This port opens the name as a file, because
`kal_fs_set_modified` takes a `kal_file` and openkal has no form of it taking a
directory or a name. What a backend says about opening a directory as a file is
the backend's: Linux distinguishes a directory and answers
`kal_err_is_directory`; the system with no such distinction answers
`kal_err_permission`, which is EACCES, which is 13.
So the refusal is asserted and the value is reported:
ok: a directory reports its modification time
note: refused with errno=21
ok: setting a directory's modification time is refused
Asserting the value would have made an observation about one implementation
while reading as an observation about the port -- which is the same mistake, in
a smaller place, as the one this round exists to fix. README.md's row now names
both values and says which is measured where, and the document records the
correction rather than being edited to look as if it had been right.
Measured after removing `target/` and building once: 47 observations, 0
failures. The first run of this was made against a stale artefact --- two
fingerprint directories existed, because the repin changed a dependency version,
and `find | head -1` answered with the older one. `tools/one-artifact.sh` exists
for exactly that and refuses rather than guessing; it is what should have been
used, and it is what produced the reading above.1 parent 250f002 commit 4e7f0ac
6 files changed
Lines changed: 564 additions & 5 deletions
File tree
- .agents/docs
- .github/workflows
- examples/posix/src
- port/src
0 commit comments