Skip to content

Commit fcb1b26

Browse files
committed
A bounded wait answers with one of three values and no others
⚠️⚠️ 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.
1 parent 6e47851 commit fcb1b26

1 file changed

Lines changed: 43 additions & 7 deletions

File tree

src/timeout.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,22 @@ int bound_ms(kal_u64 ns) {
5151
}
5252

5353
// Whether this word names a socket, which is the first question because a
54-
// socket also reports `FILE_TYPE_PIPE'. `getsockname' is the enquiry that
55-
// answers it: upon a socket it succeeds or fails for a reason of its own, and
56-
// upon anything else this system reports `WSAENOTSOCK'.
54+
// socket also reports `FILE_TYPE_PIPE'.
55+
//
56+
// ⚠️ THE TEST IS THAT `getsockname' SUCCEEDS, AND NOT THAT IT FAILED FOR SOME
57+
// PARTICULAR REASON. The first form of this function read "it is a socket
58+
// unless the failure was WSAENOTSOCK", which makes the answer depend on which
59+
// error a system chooses for a handle that is not one --- and Wine does not
60+
// choose the same one. Every socket this implementation hands out has been
61+
// connected, bound or accepted, so `getsockname' succeeds upon all of them;
62+
// anything it cannot answer for is treated as not a socket, and the file type
63+
// then decides.
5764
bool is_socket(SOCKET s) {
5865
auto* n = okw::net_or_null();
5966
if (n == nullptr) return false;
6067
ksockaddr_storage ss{};
6168
int len = static_cast<int>(sizeof ss);
62-
if (n->sockname(s, &ss, &len) == 0) return true;
63-
return n->last_error() != okw::WSAENOTSOCK;
69+
return n->sockname(s, &ss, &len) == 0;
6470
}
6571

6672
enum class shape { socket, pipe, ready, none };
@@ -81,6 +87,13 @@ int await(SOCKET s, short events, kal_u64 ns) {
8187
if (n == nullptr) return kal_err_not_supported;
8288
WSAPOLLFD_ p{ s, events, 0 };
8389
const int r = n->poll(&p, 1, bound_ms(ns));
90+
// ⭐ THE REAL ERROR IS KEPT HERE AND NARROWED IN `await_stream'. This
91+
// function is reached with a socket this implementation made --- from
92+
// `kal_timeout_accept' and `kal_timeout_recv_from', where the resource is
93+
// known --- so a failure carries information a caller can act upon. It is
94+
// reached with a caller's stream through `await_stream', where the resource
95+
// is not known, and that is where the answer is narrowed to the set the
96+
// interface defines.
8497
if (r < 0) return okw::last_socket_error();
8598
if (r == 0) return kal_err_again; // the bound expired
8699
// A socket reported as failed or hung up is ready in the sense that the
@@ -106,7 +119,12 @@ int await_pipe(HANDLE h, kal_u64 ns) {
106119
if (!PeekNamedPipe(h, nullptr, 0, nullptr, &available, nullptr)) {
107120
const DWORD e = GetLastError();
108121
if (e == ERROR_BROKEN_PIPE || e == ERROR_PIPE_NOT_CONNECTED) return kal_ok;
109-
return okw::translate_win32(e);
122+
// ⚠️ A FAILURE OF THE ENQUIRY IS NOT AN ERROR OF THE TRANSFER, and
123+
// reporting it as one would put this operation's answer outside the
124+
// set the interface defines for it. What this call could not do is
125+
// BOUND the operation; the transfer that follows reports whatever
126+
// is wrong with the resource, in the words it already uses.
127+
return kal_err_not_supported;
110128
}
111129
if (available > 0) return kal_ok;
112130
if (ms == 0) return kal_err_again;
@@ -118,6 +136,20 @@ int await_pipe(HANDLE h, kal_u64 ns) {
118136
}
119137
}
120138

139+
// ⭐⭐ EVERY PATH OUT OF THIS FUNCTION IS ONE OF THREE: kal_ok, kal_err_again,
140+
// kal_err_not_supported.
141+
//
142+
// That is the set `openkal.timeout' defines for the WAIT it adds, and keeping
143+
// to it is what makes a bounded operation distinguishable from an ordinary one.
144+
// An error belonging to the RESOURCE --- an invalid handle, a reset connection
145+
// --- is the transfer's to report, and the transfer follows this call.
146+
//
147+
// ⚠️ MEASURED TWICE, BOTH TIMES AS THE SAME SHAPE. An earlier form returned
148+
// `kal_err_invalid' for a handle of zero; a later one returned whatever
149+
// `PeekNamedPipe' or `WSAPoll' had failed with. The conformance suite reported
150+
// both as "a bounded read reports success, an expiry, or a refusal" not
151+
// holding, and the second time only under Wine --- which is to say, only where
152+
// the system chose a different error for the same condition.
121153
int await_stream(kal_stream s, short events, kal_u64 ns) {
122154
// ⚠️ ONE REASON TO REFUSE, AND NOT TWO. An earlier form answered a null or
123155
// invalid handle with `kal_err_invalid' and everything else with
@@ -132,7 +164,11 @@ int await_stream(kal_stream s, short events, kal_u64 ns) {
132164
// resource.
133165
const SOCKET raw = static_cast<SOCKET>(s.h);
134166
switch (shape_of(raw)) {
135-
case shape::socket: return await(raw, events, ns);
167+
case shape::socket: {
168+
const int r = await(raw, events, ns);
169+
// Narrowed here and not in `await': see the note there.
170+
return (r == kal_ok || r == kal_err_again) ? r : kal_err_not_supported;
171+
}
136172
case shape::pipe:
137173
// Writability is not enquired of: this system has no call that
138174
// reports whether a pipe would accept bytes without blocking, and a

0 commit comments

Comments
 (0)