Skip to content

Commit 4e7f0ac

Browse files
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

0 commit comments

Comments
 (0)