Skip to content

0.8.0 --- openkal 0.13: whether a node may be started, and a start that is not a program - #24

Merged
Sunrisepeak merged 4 commits into
mainfrom
openkal-0.13
Sep 17, 2026
Merged

Sunrisepeak merged 4 commits into
mainfrom
openkal-0.13

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Summary

  • kal_err_not_program maps ERROR_BAD_EXE_FORMAT and ERROR_EXE_MACHINE_TYPE_MISMATCH (plus the same header-validation family, ERROR_INVALID_EXE_SIGNATURE/ERROR_EXE_MARKED_INVALID). Measured under Wine: CreateProcessW upon a text file with no recognised extension returns ERROR_BAD_EXE_FORMAT (193).
  • kal_fs_set_executable_at is exported and does not claim KAL_FS_PROP_EXECUTABLE: this system's ordinary volumes do not record whether a node may be started, so the operation validates its arguments and reports kal_err_not_supported.
  • Independent bug, fixed alongside: a spawn now inherits only the handles it placed. CreateProcessW with inheritance enabled used to hand the started program every inheritable handle of the caller, not only the three named in the start-up record — a detached child could keep a starter's own standard output open long after the starter had gone. Fixed with STARTUPINFOEXW + PROC_THREAD_ATTRIBUTE_HANDLE_LIST naming exactly the deduplicated, non-null placed handles. Covered by a new test, tests/handle_inheritance.cpp.
  • The two directions of a connection are independent (clause 6.6). Sockets are now created with WSA_FLAG_OVERLAPPED; a synchronous handle on this system shares one completion event across operations, so a read blocked in one context held back a write from another on the same connection. kal_stream_read/kal_stream_write and kal_datagram_send_to/recv_from now issue their transfers through their own OVERLAPPED and wait for it, so the two directions no longer contend. Files and pipes (not overlapped) are unaffected.
  • Version 0.8.0; openkal dependency 0.13.0.
  • Comments carry no emoji (repo-wide pass).

Verification

Local, under Wine (wine-9.0), cross-built for x86_64-windows-gnu against the sibling openkal working tree on branch openkal-0.13:

  • Conformance suite (full,exec,random,terminal,net,datagram,timeout): 174 held, 0 did not hold, 6 not observed (the 6 are volume properties this environment does not have — links, locks, executable-recording — each correctly reported as not observed rather than failing).
  • tests/handle_inheritance.cpp: green under the fix. I additionally reverted src/process.cpp to the pre-fix version and re-ran the same test to attempt a red-before/green-after pair; under Wine the pre-fix version also passed — Wine's process/handle-inheritance model does not appear to reproduce this specific NT quirk (unrestricted bInheritHandles handing over every inheritable handle) as faithfully as real Windows does, so the regression could not be demonstrated red locally. The fix follows documented Win32 semantics and is covered by this PR's conformance job, which runs on native windows-2022 runners.
  • Surface check (check-surface.sh --complete): 102 names, complete and conformant.
  • "every declared name is exported by a .def" check: 72 declared, 75 exported, ok.
  • Independence check (no C-runtime symbol), dev and release profiles: both clean.
  • mcpp.toml verified to have no local/absolute path left in it after each of the above (the scripts' own trap-restore, checked by hand).

Test plan

  • CI: conformance job (native windows-2022, three toolchain rows) — watching.
  • CI: cross job (Wine + surface + independence) — watching.

…at is not

a program

kal_err_not_program maps ERROR_BAD_EXE_FORMAT and ERROR_EXE_MACHINE_TYPE_MISMATCH,
this loader's two reports of a name that exists and is not a form it can start
(ERROR_INVALID_EXE_SIGNATURE and ERROR_EXE_MARKED_INVALID, the same header-
validation family, are mapped with them). Measured under Wine: CreateProcessW
upon a text file with no recognised extension returns ERROR_BAD_EXE_FORMAT (193).

kal_fs_set_executable_at is exported and does not claim KAL_FS_PROP_EXECUTABLE:
this system's ordinary volumes do not record whether a node may be started, so
the operation validates its arguments as its siblings do and reports
kal_err_not_supported rather than simulate a property nothing here stores.
kal_fs_info and kal_fs_file_info already left KAL_INFO_EXECUTABLE out of
present, which needed no change.

A spawn inherits only the handles it placed. CreateProcessW with inheritance
enabled handed the started program every inheritable handle of this process,
not only the three this operation named --- a defect independent of the
specification, and the one a detached child's leaked standard output was
found by: a program that kept the pipe open long after its starter had gone
made whoever waited for the end of it wait for the wrong program. The fix is
STARTUPINFOEXW with PROC_THREAD_ATTRIBUTE_HANDLE_LIST naming exactly the
deduplicated, non-null standard handles this start placed; every other
inheritable handle of the caller no longer crosses. tests/handle_inheritance.cpp
proves it directly: an inheritable handle made for a reason of its own and
never placed is not inherited, observed under Wine.

The two directions of a connection are independent, clause 6.6. Every socket
is now made with WSA_FLAG_OVERLAPPED; a synchronous handle on this system
shares one completion event between whatever operations are issued upon it,
so a read blocked in one context held back a write from another on the same
connection, which is exactly what clause 6.6 forbids. kal_stream_read/write
issue ReadFile/WriteFile with an OVERLAPPED of their own for a socket and wait
for it synchronously; a file or a pipe, neither of which is overlapped, is
unaffected. kal_datagram_send_to/recv_from do the same through
WSASendTo/WSARecvFrom, so a datagram socket's two directions do not contend
either. The conformance suite's new observation, that a write is not delayed
by a read waiting on the same connection, holds.

Comments carry no emoji.
…GSIZE

Measured on windows-2022 (this PR's own CI): a message too large for the
buffer, received through the overlapped WSARecvFrom this version introduced,
completes with STATUS_BUFFER_OVERFLOW; GetOverlappedResult reports that
through the generic Win32 channel as ERROR_MORE_DATA, not as the
Winsock-specific WSAEMSGSIZE the immediate-failure path gives and the rest of
src/datagram.cpp already checks for. The two are normalised to one where the
overlapped result is read, so the truncation this interface requires to be
reported as a success (the bytes that fit, not a failure) is recognised
regardless of which path the completion took. Wine did not reproduce the
distinction; both toolchain rows on windows-2022 did.
…ormance step beside it already does

The gcc/gnu-CRT row's mcpp test, run with no --target, did not pick up
[target.'cfg(all(windows, not(env = "msvc")))'.build].ldflags -- the import
libraries this package's own objects need (ntdll, synchronization, bcrypt) --
and every test failed to link: undefined references to __imp_NtCreateFile,
__imp_WaitOnAddress, __imp_BCryptGenRandom, and the rest, all from openkal-windows's
own objects the test links against. Passing --target x86_64-windows-gnu, matching
the matrix and the step beside it, resolves it: a local cross build with the same
flag links and runs handle_inheritance cleanly.
Recorded after review. 0.7 made sockets synchronous so that a started program
could treat one as a pipe; 0.8 makes them overlapped for the independence of
the two directions. A started program that issues synchronous transfers on an
inherited socket is outside what the system defines, and a caller relays the
connection through a channel instead.
@Sunrisepeak
Sunrisepeak merged commit bce0732 into main Sep 17, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant