Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ An implementation of [openkal](https://github.com/mcpplibs/openkal) for Windows.
openkal = "0.17.1"

[target.'cfg(windows)'.dependencies]
openkal-windows = "0.13.1"
openkal-windows = "0.13.2"
```

Its purpose is as much to test the specification as to be used. openkal was
Expand Down
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-windows"
version = "0.13.1"
version = "0.13.2"
description = "An implementation of openkal for Windows, written on the Win32 interfaces and the object manager beneath them, using no C runtime symbol."
license = "Apache-2.0"

Expand Down
12 changes: 12 additions & 0 deletions src/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,18 @@ inline void* process_of(kal_process p) {
}
}


} // namespace

namespace okw {
// The process handle a word names, for the operations outside this file that
// wait on a started program (timeout.cpp): a word of a program started with a
// bound lifetime names its record, not its handle (0.13.2).
void* process_handle(kal_process p) { return process_of(p); }
} // namespace okw

namespace {

// EVERY ENVIRONMENT ENTRY IS `NAME=value' (0.17, process.h).
bool entries_well_formed(const char** envp, const kal_uintptr* lens, kal_uintptr n) {
for (kal_uintptr i = 0; i < n; ++i) {
Expand Down
9 changes: 8 additions & 1 deletion src/timeout.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "win.h"
#include "endpoint.h"
#include <openkal/timeout.h>
#include <openkal/process.h>

namespace okw { void* process_handle(kal_process p); }

// openkal.timeout on this system.
//
Expand Down Expand Up @@ -227,7 +230,11 @@ kal_intptr kal_timeout_recv_from(kal_datagram d, void* buf, kal_uintptr len,
}

int kal_timeout_wait_process(kal_process p, kal_u64 ns, int* status, int* terminated) {
void* h = okw::unpack(p.h);
// THE WORD'S KIND DECIDES WHAT IT NAMES (0.13.2). A program started with a
// bound lifetime is named by its record, and reading the word as a handle
// waited upon nothing: every bounded wait for such a program failed, so a
// caller bounding it waited without a bound or not at all.
void* h = okw::process_handle(p);
if (h == nullptr) return kal_err_invalid;

// THE ONE OPERATION OF THIS INTERFACE THIS SYSTEM PROVIDES DIRECTLY. The
Expand Down
71 changes: 71 additions & 0 deletions tests/bounded_wait_of_a_bound_program.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// A bounded wait for a program started with a bound lifetime (0.13.2).
//
// Such a program is named by its record rather than by its handle, and
// `kal_timeout_wait_process' read the word as a handle: every bounded wait for
// it failed. A caller that bounds a command (mcpp's `[hooks] timeout_seconds')
// then waited without the bound. The wait expires while the program runs and
// reports its status once it has ended.
#include <cstdio>
#include <cstring>
#include <openkal/fs.h>
#include <openkal/process.h>
#include <openkal/timeout.h>
#include <openkal/types.h>

namespace {

int failures = 0;

void check(bool held, const char* what) {
if (held) { std::printf("ok: %s\n", what); return; }
std::printf("FAIL: %s\n", what);
++failures;
}

bool system_volume(kal_dir* volume) {
const kal_uintptr count = kal_fs_preopen_count();
for (kal_uintptr i = 0; i < count; ++i) {
char name[16]{};
kal_uintptr len = 0;
kal_dir d{};
if (kal_fs_preopen(i, &d, name, sizeof name, &len) != kal_ok) continue;
if (len == 2 && (name[0] | 0x20) == 'c' && name[1] == ':') { *volume = d; return true; }
}
return false;
}

// The interpreter running `command', with a lifetime bound to this program.
int start(const char* command, kal_process* p) {
kal_dir volume{};
if (!system_volume(&volume)) return -1;
const char* path = "Windows/System32/cmd.exe";
const char* argv[3] = { "cmd.exe", "/c", command };
const kal_uintptr lens[3] = { 7, 2, std::strlen(command) };
const kal_spawn how{ volume, volume, nullptr, nullptr, 0, KAL_SPAWN_BOUND_LIFETIME };
return kal_process_spawn(&how, path, std::strlen(path), argv, lens, 3, nullptr, nullptr, 0, nullptr, p);
}

} // namespace

int main() {
if ((kal_process_props() & KAL_PROCESS_PROP_BOUND_LIFETIME) == 0) {
std::printf("openkal-windows: no bound lifetime here; nothing to observe\n");
return 0;
}
kal_process slow{};
check(start("ping -n 3 127.0.0.1 >NUL", &slow) == kal_ok, "a bound program starts");
int status = -1, terminated = -1;
check(kal_timeout_wait_process(slow, 100000000ull /* 100 ms */, &status, &terminated) == kal_err_again,
"a bounded wait expires while the bound program runs");
check(kal_timeout_wait_process(slow, 20000000000ull /* 20 s */, &status, &terminated) == kal_ok
&& status == 0,
"and reports its status once it has ended");

kal_process quick{};
check(start("exit 3", &quick) == kal_ok, "a second bound program starts");
check(kal_timeout_wait_process(quick, 20000000000ull, &status, &terminated) == kal_ok && status == 3,
"a bounded wait reports the status the program returned");

if (failures == 0) std::printf("openkal-windows: a bound program is waited for with a bound\n");
return failures == 0 ? 0 : 1;
}
Loading