@ai-ecoverse/slicc-kernel 1.42.3 → 1.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/kernel-worker.js +11 -2
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +71 -12
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +11 -2
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +71 -12
- package/dist/process-worker.js.map +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -174,6 +174,7 @@ On top of preview1 a WASI program gets:
|
|
|
174
174
|
|
|
175
175
|
- **Threads**: `wasi.thread-spawn` (wasm32-wasip1-threads) and WASIX `thread_spawn_v2` start a worker per thread on the process's shared memory, sized from the module's own import (a 2 GiB maximum when the engine cannot reserve more). The threads share one descriptor table; `exit` or a trap in any thread ends the process. At most 64 threads per process; `SLICC_WASM_THREADS` sets another cap, up to 256.
|
|
176
176
|
- **WASIX** (a module importing `wasix_32v1`): fork and setjmp/longjmp through Asyncify (the module is built with `wasm-opt --asyncify`), exec, `posix_spawn`, `waitpid`, pipes, `dup2`, signal handlers and interval timers, terminal modes, and dynamic linking: a position-independent main module loads side modules with `dlopen` from `LD_LIBRARY_PATH`, its runtime path, `/lib`, `/usr/lib` and `/usr/local/lib`.
|
|
177
|
+
- **Job control:** `^Z`, `SIGTSTP`, `SIGTTIN` and `SIGTTOU` stop a WASIX program at once, unless it has a handler for them. A stopped program that is busy computing is stopped for job control (`jobs` shows it, `fg`, `bg` and `SIGCONT` work), but its worker keeps a core busy until its next system call, since a worker's running code cannot be frozen from outside. Agents should `kill` such a job rather than leave it stopped.
|
|
177
178
|
- **Sockets**: the WASIX socket calls (`sock_open`, `sock_pair` for an `AF_UNIX` stream pair, `bind`, `listen`, `connect`, `accept`, options, local and peer names) are the kernel's loopback sockets, and preview1's `sock_recv` / `sock_send` / `sock_shutdown` work on them and on inherited ones. Writing to a socket whose peer is gone fails with `EPIPE`, through `fd_write` as through `sock_send`, as if `MSG_NOSIGNAL` were set, since a WASI program cannot ignore `SIGPIPE`; a pipe or terminal whose reader is gone still ends the program with status 141. HTTP and HTTPS leave through the realm proxy that `https_proxy` names, as for any other program; `resolve` answers `/etc/hosts` names and literal addresses, and the [uplink](#uplink)'s names.
|
|
178
179
|
- **Diagnostics**: a trap ends the program with 134 and its message on stderr; with `SLICC_WASM_BACKTRACE=1` the wasm frames follow, named from the module's name section, or from a sidecar for a module shipped without one (`<module>.names` beside it, or the same path in a `<package>-names` package). `SLICC_WASI_STATS=1` makes a program print its calls, counted and timed, as it ends.
|
|
179
180
|
|
|
@@ -209,7 +210,7 @@ The module's default export (or its `main` export) is called with a context and
|
|
|
209
210
|
- `sync`: `read`, `write`, `close`, `open` (whose files' methods are synchronous too) and `fs`, made synchronously, for code that cannot `await`, such as a compiled program's file system or a `readFileSync`. A synchronous call holds the worker until the kernel answers, so nothing else of the program runs meanwhile, timers and callbacks included; a signal that arrives during a blocked read or write runs its handler, and the call is then restarted. Descriptors are shared with the rest of the context, so a file opened with `sync.open` can be closed with `close`, and the other way around;
|
|
210
211
|
- `spawn({ argv, env, cwd, stdin, stdout, stderr })` starts a command (found as `kernel.run` finds it) as a child process and resolves with `{ pid, stdin, stdout, stderr, wait(), kill(signal) }`. Each stdio is `'inherit'` (the default: the program's own), `'pipe'` (a web stream on a kernel pipe), `'null'`, or one of the program's descriptors. `env` is the child's whole environment (the program's by default), and `cwd` defaults to the program's. A command that does not exist rejects with `ENOENT`;
|
|
211
212
|
- `wait(pid)` resolves with `{ status }` once a child ends, or `{ status: 128 + signal, signal }` when a signal ended it, without blocking the program; `kill(pid, signal)` signals any process, by number or as `'SIGTERM'` (the default);
|
|
212
|
-
- `net`: `listen({ port, host, backlog })` and `connect({ host, port, signal })` on the kernel's loopback, the same sockets WASIX programs use, so a JS server is reached by other processes, by the page as `<port>.kernel.localhost` (`loopbackFetch`, `dial`) and by attached clients. A listener has its `port` (as bound, so port `0` picks a free one), `accept({ signal })`, `close()` and `for await` over its connections. A connection has `local` and `remote` addresses, `readable` and `writable` web streams (closing the writable shuts down the sending side, so the peer reads the end), and `close()`. The loopback is IPv4 (`127.0.0.1` by default, or `0.0.0.0`), and binding and connecting fail as they would for a WASIX program (`EADDRINUSE`, `ECONNREFUSED`, `EADDRNOTAVAIL`). A blocked accept, read or write waits without holding anything in the kernel, so aborting it or closing the socket leaves nothing behind. A write to a connection the peer closed fails with `EPIPE` and no `SIGPIPE`;
|
|
213
|
+
- `net`: `listen({ port, host, backlog })` and `connect({ host, port, signal })` (`host` defaults to `127.0.0.1`) on the kernel's loopback, the same sockets WASIX programs use, so a JS server is reached by other processes, by the page as `<port>.kernel.localhost` (`loopbackFetch`, `dial`) and by attached clients. A listener has its `port` (as bound, so port `0` picks a free one), `accept({ signal })`, `close()` and `for await` over its connections. A connection has `local` and `remote` addresses, `readable` and `writable` web streams (closing the writable shuts down the sending side, so the peer reads the end), and `close()`. The loopback is IPv4 (`127.0.0.1` by default, or `0.0.0.0`), so an IPv6 host such as `::1` fails with `EADDRNOTAVAIL` for both `listen` and `connect`, and binding and connecting fail as they would for a WASIX program (`EADDRINUSE`, `ECONNREFUSED`, `EADDRNOTAVAIL`). A blocked accept, read or write waits without holding anything in the kernel, so aborting it or closing the socket leaves nothing behind. A write to a connection the peer closed fails with `EPIPE` and no `SIGPIPE`;
|
|
213
214
|
- `exit(status)`, which ends the program once its pending writes are done.
|
|
214
215
|
|
|
215
216
|
A program that throws, or leaves an error or a rejected promise unhandled, ends with status 1 and the message on stderr; one whose module cannot be loaded, or exports no function, ends with 126. A write to a pipe whose reader is gone ends the program with 141, unless it ignores or catches `SIGPIPE` (an ignore inherited from its parent counts), in which case the write fails with `EPIPE`. Errors carry a POSIX `code`. Reads and writes of pipes, terminals and sockets go through the kernel's asynchronous operations, so a program blocked reading stdin can still write and handle signals; other calls of one process are made one at a time. A JS program cannot `fork`, and threads it starts itself are not the kernel's.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -9014,7 +9014,10 @@ var WasmProcess = class {
|
|
|
9014
9014
|
this.children.onReap = options.onReap;
|
|
9015
9015
|
}
|
|
9016
9016
|
ignores(bit) {
|
|
9017
|
-
return (
|
|
9017
|
+
return (this.signalMasks().ignored & bit) !== 0;
|
|
9018
|
+
}
|
|
9019
|
+
signalMasks() {
|
|
9020
|
+
return { ignored: this.ignored | this.inherited & ~this.caught, caught: this.caught };
|
|
9018
9021
|
}
|
|
9019
9022
|
inheritable(fork = false) {
|
|
9020
9023
|
return ((fork ? 0 : this.ignored) | this.inherited) & ~this.caught;
|
|
@@ -9895,6 +9898,7 @@ function spawnWasmProcess(opts) {
|
|
|
9895
9898
|
onState: (listener) => process.onState(listener),
|
|
9896
9899
|
memory: () => Atomics.load(header2, SAB_I_MEMORY) * 65536,
|
|
9897
9900
|
ignoredSignals: (fork) => process.inheritable(fork),
|
|
9901
|
+
signalMasks: () => process.signalMasks(),
|
|
9898
9902
|
umask: () => process.umask,
|
|
9899
9903
|
writesBack: () => opts.program.abi === "wasi" && !done4
|
|
9900
9904
|
};
|
|
@@ -11782,7 +11786,8 @@ var Launcher = class {
|
|
|
11782
11786
|
started: (this.described.get(root.pid) ?? described).started,
|
|
11783
11787
|
state: this.processes.has(member.pid) ? "S" : "Z",
|
|
11784
11788
|
memory: this.processes.get(member.pid)?.memory() ?? 0,
|
|
11785
|
-
umask: this.umaskOf(member.pid)
|
|
11789
|
+
umask: this.umaskOf(member.pid),
|
|
11790
|
+
...this.signalMasksOf(member.pid)
|
|
11786
11791
|
});
|
|
11787
11792
|
}
|
|
11788
11793
|
return listed;
|
|
@@ -11868,6 +11873,10 @@ var Launcher = class {
|
|
|
11868
11873
|
const open = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
|
|
11869
11874
|
if (!open) void this.mounts.commit(at).catch(() => void 0);
|
|
11870
11875
|
}
|
|
11876
|
+
signalMasksOf(pid) {
|
|
11877
|
+
const masks = this.processes.get(pid)?.signalMasks?.();
|
|
11878
|
+
return masks ? { sigIgn: masks.ignored, sigCgt: masks.caught } : {};
|
|
11879
|
+
}
|
|
11871
11880
|
ignoredBy(pid, fork = false) {
|
|
11872
11881
|
return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
|
|
11873
11882
|
}
|