Skip to content

Provide net, datagram, timeout and exec; decline space in terms - #14

Merged
Sunrisepeak merged 5 commits into
mainfrom
feat/capability-completeness
Aug 27, 2026
Merged

Provide net, datagram, timeout and exec; decline space in terms#14
Sunrisepeak merged 5 commits into
mainfrom
feat/capability-completeness

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

This implementation declined all five interfaces openkal 0.8 added. Four of
them this system has, and the fifth it does not
— which is a legitimate
outcome rather than a gap, and is now stated as one.

on this system
src/net.cpp Winsock, started once at the first socket and never stopped
src/datagram.cpp the same calls with SOCK_DGRAM
src/timeout.cpp WSAPoll, which answers for sockets and for nothing else
src/exec.cpp VirtualAlloc, VirtualProtect, FlushInstructionCache

⭐⭐ WSASocketW with a flags word of zero, and that zero is load-bearing

The ordinary socket makes an overlapped handle, upon which ReadFile
returns before the bytes have arrived. A flags word of zero makes one that is
not — and that is what lets a connection be a stream here, because
openkal.stream on this system is ReadFile and WriteFile. Without it this
implementation would need a second transfer path.

A change to that one zero would neither fail to compile nor fail to link.
src/win32.h and port/ws2_32.def both say so beside the name.

openkal.space stays declined, in terms

CreateProcessW starts a named program, which is openkal.process and a
different operation. Constructing a copy of the calling address space out of it,
plus a mechanism for carrying the caller's memory across, would be the
simulation clause 3.1 forbids: present, shaped like the operation, and producing
something that is not a copy of the caller.

A program that calls kal_space_start therefore fails at the link, naming
the operation, which is clause 6.1's report and the loudest one available.

⚠️ Three constants differ from the other systems' without announcing it

AF_INET6 is 23 here, 30 on macOS, 10 on Linux. SOL_SOCKET is 0xffff
here and on macOS, 1 on Linux. And this system's poll has no bit named
POLLIN
— what it has is POLLRDNORM, and the Linux value asks about
out-of-band data instead.

Two behavioural differences are recorded rather than smoothed over:

  • SO_REUSEADDR is not the same option here. On the other two it permits a
    listener whose predecessor is lingering; here it permits two listeners on one
    address at once
    . It is therefore not set — setting it for symmetry would make
    this implementation behave differently while looking the same.
  • A truncated datagram is reported as a failure here and truncated silently
    elsewhere. The bytes that fit are delivered either way, and the interface states
    that the excess is lost.

⚠️⚠️ The conformance run was selecting less than its step name said

full expands to the hosted set, so every optional interface — random and
terminal included, which this implementation has provided since before 0.8 —
was compiled with its section body removed and reported as not examined.

The set is now enumerated: the six this system provides, and not optional,
because optional names space and a set demanding it would fail to link
rather than report an observation.

Measured here rather than remembered

16 objects; exported surface complete and conforming at 88 names (the two
absent are openkal.space's, and --complete is checked group by group); no
undefined symbol outside the permitted set.


This is one change across seven repositories, and every branch carries the
same name.
Each repository's continuous integration substitutes its siblings'
working trees taken from the branch of the name under test, so the graph only
holds together when they agree.

repository what it carries
openkal-musl the socket, datagram, readiness and image-copying routes, and four probes
openkal-macos the five interfaces 0.8 added
openkal-windows four of the five; openkal.space declined in terms
openkal-linux the conformance run selects the optional interfaces, which nothing did
openkal-llvm-runtime __config_site's claims asserted by a program, and the C library repinned
openkal the portable example's pins, and §9 of the plan
sbase ninety-seven utilities above the new C library

The specification does not change. No interface was added, none was altered,
and SURFACE.txt is untouched — every capability below is composed from atoms
openkal 0.8 already had.

This implementation declined all five interfaces openkal 0.8 added.
Four of them this system has, and the fifth it does not --- which is a
legitimate outcome rather than a gap, and is now stated as one.

  src/net.cpp       Winsock. ⚠️ `WSASocketW' with a flags word of zero
                    rather than `socket': the latter makes an OVERLAPPED
                    handle, upon which `ReadFile' returns before the
                    bytes have arrived. A non-overlapped socket is what
                    lets a connection BE a stream here --- openkal.stream
                    is `ReadFile' and `WriteFile' on this system --- with
                    no second transfer path. A change to that one zero
                    would neither fail to compile nor fail to link.
  src/datagram.cpp  the same calls with SOCK_DGRAM. ⚠️ This system
                    reports a truncated message as a FAILURE where the
                    other two truncate silently; the bytes that fit are
                    delivered either way, and the interface states that
                    the excess is lost.
  src/timeout.cpp   `WSAPoll', which answers for sockets and for nothing
                    else. A bounded transfer upon a stream that is not a
                    socket reports kal_err_not_supported, which the
                    interface's own header anticipates in terms.
                    `kal_timeout_wait_process' is the one operation of
                    this interface the system provides DIRECTLY.
  src/exec.cpp      VirtualAlloc, VirtualProtect, FlushInstructionCache.
                    The third is not optional.

openkal.space stays declined. `CreateProcessW' starts a NAMED PROGRAM,
which is openkal.process and a different operation; constructing a copy
of the calling address space out of it would be the simulation clause
3.1 forbids. A program that calls `kal_space_start' fails at the link
naming the operation, which is clause 6.1's report.

⚠️ THREE CONSTANTS DIFFER FROM THE OTHER SYSTEMS' WITHOUT ANNOUNCING IT:
AF_INET6 is 23 here, 30 on macOS and 10 on Linux; SOL_SOCKET is 0xffff
here and on macOS and 1 on Linux; and this system's `poll' has no bit
named POLLIN --- what it has is POLLRDNORM, and the Linux value asks
about out-of-band data instead.

⚠️⚠️ AND THE CONFORMANCE RUN WAS SELECTING LESS THAN ITS STEP NAME SAID.
`full' expands to the HOSTED set, so every optional interface --- random
and terminal included, which this implementation has provided since
before 0.8 --- was compiled with its section body removed and reported
as not examined. The set is now enumerated: the six this system
provides, and not `optional', because `optional' names `space'.

Measured here rather than remembered: 16 objects, exported surface
complete and conforming at 88 names, and no undefined symbol outside the
permitted set.
⚠️⚠️ THIS SYSTEM'S NETWORK LIBRARY EXPORTS THE BSD NAMES, AND SO DOES THE
C LIBRARY ABOVE THIS IMPLEMENTATION. openkal-musl compiles musl's own
`src/network/*.c', which define `bind', `listen', `accept' and `connect'
and route them through this port. Naming `-lws2_32' on the link line put
both definitions in one program:

    ld.exe: libws2_32.a(libws2_32s00165.o): multiple definition of
            `connect'; musl/src/network/connect.o: first defined here

Measured on the GNU/PE row of the C library's own continuous integration,
on the first run of this change. It is not an ordering problem: an import
library's member defines the thunk AND the `__imp_' pointer together, so
reaching for either brings both.

⭐ THE NAMES ARE THEREFORE REACHED THROUGH THE SYSTEM'S OWN LOADER
--- `LoadLibraryW' and `GetProcAddress', both of which this package
already links --- into a table resolved once. Nothing of ws2_32 enters
the program's symbol table, so the C library above keeps its `bind' and
this implementation still reaches the system's.

`port/ws2_32.def', the `-lws2_32' flag and the `#pragma comment' all come
out. The table is resolved ENTIRELY OR NOT AT ALL: a table with one null
entry would make the operations that resolved work and the one that did
not call through zero, which is the failure clause 6.1 exists to turn
into a link error and this arrangement cannot.

Measured here after the change: `examples/cross-hello' links and produces
`cross-hello.exe' over this implementation and that C library; 16
objects; exported surface complete and conforming at 88 names; no
undefined symbol outside the permitted set; and NO BSD NAME DEFINED in
this package's own objects, which is the property the collision was about.
Two failures, both from the conformance run this change made selective.

⚠️ `VirtualAlloc', `VirtualProtect', `VirtualFree' and
`FlushInstructionCache' were declared in src/win32.h and exported by no
`.def'. This package's own check says so in as many words --- "declared
in src/win32.h and exported by no .def" --- and it is the check that
exists because an import library here is a list of names rather than
code, so a name absent from the list is a link that finds nothing on a
machine without a vendor SDK.

⚠️⚠️ AND `kal_timeout_read' UPON THE STANDARD INPUT HAD TWO REFUSALS
WHERE THE INTERFACE HAS ONE. An earlier form answered a null or invalid
handle with `kal_err_invalid' and a valid non-socket with
`kal_err_not_supported'; a run whose standard input is not attached has a
handle of zero, so both bounded reads in the suite were reported as not
holding.

⭐ The early return was answering a DIFFERENT QUESTION. "Is this handle
valid" is what the unbounded operation answers. What this interface
answers is whether this implementation can bound an operation upon this
resource, and timeout.h sanctions exactly one refusal for that: "AN
IMPLEMENTATION MAY PROVIDE THIS FOR SOME OF ITS RESOURCES AND NOT OTHERS,
and reports kal_err_not_supported for the rest." A handle that is not a
socket is one of the rest, and zero is not a socket.

The name/export reading is also performed here before pushing, so that a
round is not spent discovering a fifth name: 49 declared, 55 exported,
none missing.
⚠️ `WSAPoll' takes sockets and nothing else, so `kal_timeout_read' upon a
pipe reported `kal_err_not_supported' --- and `openkal.process' makes a
channel out of a pipe on this system. A C library above this
implementation therefore reaches `poll' and `select' upon one, and
openkal-musl's network probe reported it on the row that builds for this
system:

    FAIL: select reports the read end ready (errno=38)

A `select' that refuses a pipe makes every program waiting on a
subprocess's output stop.

⭐ THREE ENQUIRIES, ONE PER KIND OF OBJECT, chosen by asking what the
handle is: `WSAPoll' for a socket, `PeekNamedPipe' for a pipe, and always
ready for a file, because a read from one does not wait. ⚠️ A socket also
reports `FILE_TYPE_PIPE', so the socket enquiry is made FIRST and the
file type only decides what a non-socket is.

⭐ `PeekNamedPipe' is the one NON-DESTRUCTIVE readiness enquiry in this
whole ecosystem: it reports how many bytes are there and takes none,
which is why this implementation needs no read-ahead where the port above
it does. ⚠️ A closed writing end is READY and not an error --- the call
then fails with `ERROR_BROKEN_PIPE' and the read that follows reports the
end of input without waiting, which is what readiness asserts. Reporting
the failure would make a program that reads until end-of-input wait for
ever instead.

What remains unbounded is a character device, and `kal_err_not_supported'
is what timeout.h states for a resource an implementation does not cover.

Measured here: 16 objects, exported surface complete at 88 names, no
undefined symbol outside the permitted set, 50 declared names and none
missing from a `.def'.
⚠️⚠️ MEASURED TWICE, THE SECOND TIME ONLY UNDER WINE, WHICH IS WHAT MADE
THE SHAPE VISIBLE. `kal_timeout_read' upon the standard input reported an
error belonging to the RESOURCE where the interface defines a set for the
WAIT: first `kal_err_invalid' for a handle of zero, then whatever
`PeekNamedPipe' or `WSAPoll' had failed with. The conformance suite
reported "a bounded read reports success, an expiry, or a refusal" as not
holding both times, and the second time on one runner out of three ---
which is to say, only where the system chose a different error for the
same condition.

⇒ `await_stream' now answers with `kal_ok', `kal_err_again' or
`kal_err_not_supported' and nothing else. An error belonging to the
resource is the TRANSFER's to report, and the transfer follows the wait.

⭐ AND THE REAL ERROR IS KEPT WHERE THE RESOURCE IS KNOWN.
`kal_timeout_accept' and `kal_timeout_recv_from' are reached with a
socket this implementation made, so a failure there carries information a
caller can act upon; the narrowing happens only on the path that takes a
caller's stream, where the resource is not known.

⚠️ `is_socket' also stops depending on WHICH error a system reports for a
handle that is not a socket. It read "it is a socket unless the failure
was WSAENOTSOCK", and Wine does not choose the same value. Every socket
this implementation hands out has been connected, bound or accepted, so
`getsockname' succeeds upon all of them; the test is that it succeeds.
@Sunrisepeak
Sunrisepeak merged commit 2152d0a into main Aug 27, 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.

2 participants