@ai-ecoverse/slicc-kernel 1.34.1 → 1.35.0
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 +16 -0
- package/dist/kernel-worker.js +41 -7
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +158 -8
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +41 -7
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +158 -8
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -421,6 +421,22 @@ An exec'd program takes over the pid of the process it replaces, as on Linux: `g
|
|
|
421
421
|
- **Emscripten:** `Module.sliccKernel.execve(file, argv, env, cwd)` runs `file` as this process's new image on its fds 0, 1 and 2, waits for it, and returns its wait status, or a negative errno when it cannot start. `env` and `cwd` may be `null` for this process's own. An exec shim detects it with `typeof Module.sliccKernel.execve === 'function'` and exits with the status it returns, as `execve` never returns on success. Older shims spawn the program and then call `Module.sliccKernel.execWait(pid)`; that works the same way: a new program asks the kernel for its pid before `main`, and the kernel answers once its parent has made its next call, so an image an older shim execs also reports the pid it replaced (the wait starts once the program is loaded; should the parent make no call within 100 ms after that, the kernel answers anyway, and the image may then report its own pid; `launcher.identities` counts the programs that asked and those answered by that timeout).
|
|
422
422
|
- **WASIX:** `proc_exec` does this by itself.
|
|
423
423
|
|
|
424
|
+
### File modes and the umask
|
|
425
|
+
|
|
426
|
+
Every process has a umask in the kernel, `022` for a process the embedder starts, inherited across fork, spawn and exec and shown in `/proc/<pid>/status` (`Umask:`). The kernel applies it when a program creates a file or directory, whatever its libc does: an Emscripten program's `open` with `O_CREAT`, `mkdir` and `mknod` (so `umask 077; touch f` gives `600` in a child too), and a WASI program's `path_open` with `O_CREAT` and `path_create_directory` (`0666` and `0777` less the umask).
|
|
427
|
+
|
|
428
|
+
WASI and WASIX have no call for file modes, so the kernel adds the import module `slicc_fs`, whose functions return a preview1 errno (kernels without them answer `ENOSYS`):
|
|
429
|
+
|
|
430
|
+
| Import | Does |
|
|
431
|
+
| --- | --- |
|
|
432
|
+
| `fd_chmod(fd, mode)` | `fchmod` on an open file or directory |
|
|
433
|
+
| `path_chmod(dirfd, path, path_len, mode, flags)` | `fchmodat`; with `flags & 1` (`AT_SYMLINK_NOFOLLOW`) a symlink answers `ENOTSUP` and is never followed |
|
|
434
|
+
| `umask(mask, old_out)` | sets the process's umask and writes the previous one |
|
|
435
|
+
| `fd_mode(fd, mode_out)` | the permission bits of an open file or directory |
|
|
436
|
+
| `path_mode(dirfd, path, path_len, flags, mode_out)` | those of a path, of the link itself with `flags & 1` |
|
|
437
|
+
|
|
438
|
+
Lowering a soft resource limit (`ulimit -S -n 64`) still fails with `EPERM` in Emscripten programs: their libc's `setrlimit` is a stub compiled into the program, not a call to the kernel.
|
|
439
|
+
|
|
424
440
|
### `/proc`
|
|
425
441
|
|
|
426
442
|
Every process of the kernel has `/proc/<pid>/` with `cmdline`, `comm`, `stat`, `statm` and `status`, in the formats procps reads, and `/proc/self` is a link to the `/proc/<pid>` of the process that reads it, as on Linux (`readlink /proc/self` is its pid, the one it was exec'd under included). They come from the kernel's process table when they are opened, so a terminal sees the processes of every client; an exec'd program shows under the pid its parent knows. `/proc/uptime`, `/proc/loadavg`, `/proc/stat` and `/proc/meminfo` are there too, and `/proc/mounts`. A process with no parent in the kernel (one a page, a client or the Node entry started) has parent 1, as children of init do, in `getppid()`, `/proc/<pid>/stat` and `ps` alike, and so does a process whose parent has ended, waited for or not (`getppid()` asks the kernel each time; a shell's `$PPID` keeps the value it started with, as on Linux). Pids, parents, process groups, sessions, command lines, terminals, start and boot times are real, and so is each process's memory: the size of its wasm memory (`VSZ` and `RSS` alike, as wasm has no paging), which `/proc/meminfo` counts as used. CPU times, load and `MemTotal` (from `navigator.deviceMemory`, else 4 GiB) are placeholders. Only Emscripten processes see this `/proc`.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -7857,10 +7857,12 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
7857
7857
|
"fd-cloexec",
|
|
7858
7858
|
"fd-list",
|
|
7859
7859
|
"proc-alarm",
|
|
7860
|
+
"proc-umask",
|
|
7860
7861
|
"dl-log",
|
|
7861
7862
|
"fd-renumber",
|
|
7862
7863
|
"fd-promote",
|
|
7863
7864
|
"fd-open-tty",
|
|
7865
|
+
"fd-tty-names",
|
|
7864
7866
|
"tty-get",
|
|
7865
7867
|
"tty-set",
|
|
7866
7868
|
"tty-winsz",
|
|
@@ -7894,6 +7896,7 @@ function isWasmSyscall(req) {
|
|
|
7894
7896
|
return typeof op === "string" && SYSCALL_OPS.has(op);
|
|
7895
7897
|
}
|
|
7896
7898
|
var MAX_READ = 1024 * 1024;
|
|
7899
|
+
var DEFAULT_UMASK = 18;
|
|
7897
7900
|
var DYING = { ok: false, errno: "EINTR", message: "the process is being killed" };
|
|
7898
7901
|
var HOSTS_ONLY = new Resolver({ routes: new Routes() });
|
|
7899
7902
|
var WasmProcess = class {
|
|
@@ -7904,6 +7907,7 @@ var WasmProcess = class {
|
|
|
7904
7907
|
inherited = 0;
|
|
7905
7908
|
interrupt = new AbortController();
|
|
7906
7909
|
dying = false;
|
|
7910
|
+
umask = DEFAULT_UMASK;
|
|
7907
7911
|
execChild;
|
|
7908
7912
|
execTermsig;
|
|
7909
7913
|
stopped = 0;
|
|
@@ -7921,6 +7925,7 @@ var WasmProcess = class {
|
|
|
7921
7925
|
this.fds = fds;
|
|
7922
7926
|
this.options = options;
|
|
7923
7927
|
this.inherited = options.ignored ?? 0;
|
|
7928
|
+
this.umask = options.umask ?? DEFAULT_UMASK;
|
|
7924
7929
|
this.children = new ChildTable(fds, options.spawner, options.forker);
|
|
7925
7930
|
this.nodes = options.nodes ?? new VfsNodes(options.fs);
|
|
7926
7931
|
if (!options.nodes) options.openFiles?.add(this.nodes);
|
|
@@ -7993,6 +7998,11 @@ var WasmProcess = class {
|
|
|
7993
7998
|
return result;
|
|
7994
7999
|
}
|
|
7995
8000
|
}
|
|
8001
|
+
setUmask(mask) {
|
|
8002
|
+
const old = this.umask;
|
|
8003
|
+
if (mask !== void 0) this.umask = mask & 511;
|
|
8004
|
+
return old;
|
|
8005
|
+
}
|
|
7996
8006
|
die() {
|
|
7997
8007
|
if (this.dying) return;
|
|
7998
8008
|
this.dying = true;
|
|
@@ -8157,6 +8167,8 @@ var WasmProcess = class {
|
|
|
8157
8167
|
if (!tty) throw new KernelError("ENXIO");
|
|
8158
8168
|
return { ok: true, kind: "json", json: this.fds.install(tty.file(), 3) };
|
|
8159
8169
|
}
|
|
8170
|
+
case "fd-tty-names":
|
|
8171
|
+
return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
|
|
8160
8172
|
case "fd-select": {
|
|
8161
8173
|
const { read, write, timeoutMs } = req;
|
|
8162
8174
|
const signal = this.blockingSignal();
|
|
@@ -8388,6 +8400,8 @@ var WasmProcess = class {
|
|
|
8388
8400
|
case "proc-alarm":
|
|
8389
8401
|
this.setAlarm(req.sig, req.firstMs ?? req.ms, req.repeat ? req.ms : 0, req.timer);
|
|
8390
8402
|
return { ok: true, kind: "void" };
|
|
8403
|
+
case "proc-umask":
|
|
8404
|
+
return { ok: true, kind: "json", json: this.setUmask(req.mask) };
|
|
8391
8405
|
case "dl-log":
|
|
8392
8406
|
if (req.append) this.dlLog.push(req.append);
|
|
8393
8407
|
return { ok: true, kind: "json", json: this.dlLog.slice(req.from) };
|
|
@@ -8537,7 +8551,7 @@ var Dying = class {
|
|
|
8537
8551
|
return [typeof reported === "number" ? reported : CRASHED, void 0];
|
|
8538
8552
|
}
|
|
8539
8553
|
};
|
|
8540
|
-
function processInit(opts, sab) {
|
|
8554
|
+
function processInit(opts, sab, umask) {
|
|
8541
8555
|
const base = {
|
|
8542
8556
|
type: WASM_PROCESS_INIT,
|
|
8543
8557
|
pid: opts.shownPid ?? opts.pid,
|
|
@@ -8546,6 +8560,7 @@ function processInit(opts, sab) {
|
|
|
8546
8560
|
env: opts.env,
|
|
8547
8561
|
cwd: opts.cwd,
|
|
8548
8562
|
sab,
|
|
8563
|
+
umask,
|
|
8549
8564
|
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
|
|
8550
8565
|
};
|
|
8551
8566
|
if (opts.program.abi === "js") {
|
|
@@ -8557,11 +8572,17 @@ function processInit(opts, sab) {
|
|
|
8557
8572
|
...opts.fork ? { fork: opts.fork } : { fds: inheritedFds(opts.fds) }
|
|
8558
8573
|
};
|
|
8559
8574
|
}
|
|
8575
|
+
function inherited(opts) {
|
|
8576
|
+
return {
|
|
8577
|
+
...opts.ignored ? { ignored: opts.ignored } : {},
|
|
8578
|
+
...opts.umask !== void 0 ? { umask: opts.umask } : {}
|
|
8579
|
+
};
|
|
8580
|
+
}
|
|
8560
8581
|
function spawnWasmProcess(opts) {
|
|
8561
8582
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
8562
8583
|
const header2 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
8563
8584
|
const process = new WasmProcess(opts.pid, opts.fds, {
|
|
8564
|
-
...opts
|
|
8585
|
+
...inherited(opts),
|
|
8565
8586
|
...opts.identity ? { identity: opts.identity } : {},
|
|
8566
8587
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
8567
8588
|
spawner: opts.spawner,
|
|
@@ -8695,7 +8716,7 @@ function spawnWasmProcess(opts) {
|
|
|
8695
8716
|
};
|
|
8696
8717
|
tw.postMessage(tinit);
|
|
8697
8718
|
};
|
|
8698
|
-
const init = processInit(opts, sab);
|
|
8719
|
+
const init = processInit(opts, sab, process.umask);
|
|
8699
8720
|
worker.postMessage(init, opts.fork ? [opts.fork.memory.buffer] : []);
|
|
8700
8721
|
const signal = (sig) => {
|
|
8701
8722
|
if (process.signal(sig) !== "terminate") return;
|
|
@@ -8713,6 +8734,7 @@ function spawnWasmProcess(opts) {
|
|
|
8713
8734
|
onState: (listener) => process.onState(listener),
|
|
8714
8735
|
memory: () => Atomics.load(header2, SAB_I_MEMORY) * 65536,
|
|
8715
8736
|
ignoredSignals: (fork) => process.inheritable(fork),
|
|
8737
|
+
umask: () => process.umask,
|
|
8716
8738
|
writesBack: () => opts.program.abi === "wasi" && !done4
|
|
8717
8739
|
};
|
|
8718
8740
|
}
|
|
@@ -8818,8 +8840,13 @@ var JobTable = class {
|
|
|
8818
8840
|
return id;
|
|
8819
8841
|
}
|
|
8820
8842
|
terminalNamed(name2) {
|
|
8821
|
-
|
|
8822
|
-
|
|
8843
|
+
return this.knownTerminals().find((tty) => tty.name === name2);
|
|
8844
|
+
}
|
|
8845
|
+
terminalNames() {
|
|
8846
|
+
return this.knownTerminals().flatMap((tty) => tty.name ? [tty.name] : []);
|
|
8847
|
+
}
|
|
8848
|
+
knownTerminals() {
|
|
8849
|
+
return [.../* @__PURE__ */ new Set([...this.terminals.values(), ...this.foreground.keys()])];
|
|
8823
8850
|
}
|
|
8824
8851
|
controllingTerminal(pid) {
|
|
8825
8852
|
const member = this.members.get(pid);
|
|
@@ -10453,6 +10480,7 @@ var Launcher = class {
|
|
|
10453
10480
|
this.settling.syscall(pid, call.op);
|
|
10454
10481
|
},
|
|
10455
10482
|
...req.ignored ? { ignored: req.ignored } : {},
|
|
10483
|
+
...req.umask !== void 0 ? { umask: req.umask } : {},
|
|
10456
10484
|
program: req.program,
|
|
10457
10485
|
argv0: req.argv0,
|
|
10458
10486
|
args: req.args,
|
|
@@ -10544,7 +10572,8 @@ var Launcher = class {
|
|
|
10544
10572
|
...described,
|
|
10545
10573
|
started: (this.described.get(root.pid) ?? described).started,
|
|
10546
10574
|
state: this.processes.has(member.pid) ? "S" : "Z",
|
|
10547
|
-
memory: this.processes.get(member.pid)?.memory() ?? 0
|
|
10575
|
+
memory: this.processes.get(member.pid)?.memory() ?? 0,
|
|
10576
|
+
umask: this.umaskOf(member.pid)
|
|
10548
10577
|
});
|
|
10549
10578
|
}
|
|
10550
10579
|
return listed;
|
|
@@ -10566,6 +10595,7 @@ var Launcher = class {
|
|
|
10566
10595
|
report,
|
|
10567
10596
|
ppid,
|
|
10568
10597
|
ignored: this.ignoredBy(ppid),
|
|
10598
|
+
umask: this.umaskOf(ppid),
|
|
10569
10599
|
...exec
|
|
10570
10600
|
});
|
|
10571
10601
|
deciding?.attach();
|
|
@@ -10610,7 +10640,8 @@ var Launcher = class {
|
|
|
10610
10640
|
fds,
|
|
10611
10641
|
ppid,
|
|
10612
10642
|
fork: state,
|
|
10613
|
-
ignored: this.ignoredBy(ppid, true)
|
|
10643
|
+
ignored: this.ignoredBy(ppid, true),
|
|
10644
|
+
umask: this.umaskOf(ppid)
|
|
10614
10645
|
})
|
|
10615
10646
|
);
|
|
10616
10647
|
}
|
|
@@ -10619,6 +10650,9 @@ var Launcher = class {
|
|
|
10619
10650
|
const foreground = () => this.jobs.tcgetpgrp(tty, fallback);
|
|
10620
10651
|
this.settling.deliver(sig, pgid, send, tty.reading ? void 0 : foreground);
|
|
10621
10652
|
}
|
|
10653
|
+
umaskOf(pid) {
|
|
10654
|
+
return this.processes.get(pid)?.umask?.() ?? DEFAULT_UMASK;
|
|
10655
|
+
}
|
|
10622
10656
|
ignoredBy(pid, fork = false) {
|
|
10623
10657
|
return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
|
|
10624
10658
|
}
|