Skip to content

Commit 1f0e8b9

Browse files
committed
Examine whether the disposition was installed
Found in self-review, and it is the shape this ecosystem exists to exclude: the installation's result was discarded, so a failed one would have left a word that can never change while the caller was handed it anyway. The program would ask whether its end had been requested, be told no, and go on being told no after it had been. `kal_process_props' now agrees, because the header defines null there as the absence that position reports and the two cannot disagree. It reads the state and never arms --- asking what an implementation can do must not install a disposition.
1 parent 256ac28 commit 1f0e8b9

1 file changed

Lines changed: 29 additions & 7 deletions

File tree

src/process.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,17 @@ struct macos_sigaction {
340340
int flags;
341341
};
342342

343-
void arm_one(int signo) {
343+
// ⚠️ THE RESULT IS EXAMINED, AND THE FUNCTION EXISTS TO RETURN IT. An
344+
// installation that failed would leave a word that can never change, and
345+
// answering the caller with one is `nothing here reports success having done
346+
// nothing' in its exact form: the program would ask whether its end had been
347+
// requested, be told no, and go on being told no after it had been.
348+
bool arm_one(int signo) {
344349
macos_sigaction act{};
345350
act.handler = &stop_handler;
346351
act.tramp = reinterpret_cast<void (*)(void*, int, int, void*, void*)>(&okm_sigtramp);
347-
okm::sys(nr_sigaction, signo, reinterpret_cast<okm_long>(&act), 0);
352+
return !okm::failed(okm::sys(nr_sigaction, signo,
353+
reinterpret_cast<okm_long>(&act), 0));
348354
}
349355

350356
#endif // __aarch64__
@@ -353,11 +359,20 @@ void arm_one(int signo) {
353359

354360
const kal_u32* kal_process_stop_requested(void) {
355361
#if defined(__aarch64__)
356-
if (!__atomic_exchange_n(&g_stop_armed, 1, __ATOMIC_ACQ_REL)) {
357-
arm_one(15); // SIGTERM
358-
arm_one(2); // SIGINT
362+
// ⚠️ THREE STATES AND NOT TWO: not yet tried, armed, refused. A second
363+
// caller must be told what the first found rather than arming again --- and
364+
// must not be told `not yet tried' while the first is still inside the
365+
// installation.
366+
int state = __atomic_load_n(&g_stop_armed, __ATOMIC_ACQUIRE);
367+
if (state == 0) {
368+
// SIGTERM is the one `kal_process_terminate' sends here; SIGINT is what
369+
// an interactive stream delivers. Both are requests to end, which is the
370+
// whole of what this word reports.
371+
const bool ok = arm_one(15) && arm_one(2);
372+
state = ok ? 1 : -1;
373+
__atomic_store_n(&g_stop_armed, state, __ATOMIC_RELEASE);
359374
}
360-
return &g_stop_word;
375+
return state == 1 ? &g_stop_word : nullptr;
361376
#else
362377
// ⚠️ DECLINED ON THE OTHER ARCHITECTURE, AND NOT BECAUSE IT CANNOT BE
363378
// WRITTEN. The trampoline above has an x86_64 counterpart of the same
@@ -419,7 +434,14 @@ kal_uintptr kal_process_props(void) { return
419434
| KAL_PROCESS_PROP_CHANNEL | KAL_PROCESS_PROP_GRANT_DIR
420435
| KAL_PROCESS_PROP_JOB
421436
#if defined(__aarch64__)
422-
| KAL_PROCESS_PROP_STOP_REQUESTED
437+
// ⚠️ AND IT AGREES WITH `kal_process_stop_requested', WHICH IS A REQUIREMENT
438+
// AND NOT A COURTESY: the header defines null there as the absence this
439+
// position reports, so the two cannot disagree. It is read and never armed
440+
// --- asking what an implementation can do must not install a disposition ---
441+
// so this claims the position until an installation has actually been refused,
442+
// and stops claiming it afterwards.
443+
| (__atomic_load_n(&g_stop_armed, __ATOMIC_ACQUIRE) == -1
444+
? 0u : KAL_PROCESS_PROP_STOP_REQUESTED)
423445
#endif
424446
; }
425447

0 commit comments

Comments
 (0)