@ai-ecoverse/slicc-kernel 1.17.0 → 1.17.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 +7 -0
- package/dist/kernel-worker.js +63 -23
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +76 -55
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +63 -23
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +76 -55
- package/dist/process-worker.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -244,6 +244,13 @@ Programs mount and unmount with `mount(2)` and `umount2(2)`, so a `mount`/`umoun
|
|
|
244
244
|
- **Errors** are Linux's: `ENODEV` for an unknown type (or `hostfs` without a hook), `ENOENT` and `ENOTDIR` for the target, `EBUSY` for a target that is mounted already, and `EINVAL` for unmounting what is not a mount point.
|
|
245
245
|
- **`/proc/mounts`** escapes spaces and backslashes as Linux does, and adds `nomedium` or `failed` to the options of a mount in that state.
|
|
246
246
|
|
|
247
|
+
### Exec
|
|
248
|
+
|
|
249
|
+
An exec'd program takes over the pid of the process it replaces, as on Linux: `getpid()` and `$$` in the new image, `/proc`, `ps`, `kill` and the parent's `waitpid` all agree on that pid, and the image's parent pid is the replaced process's. Its own children see that pid as their parent.
|
|
250
|
+
|
|
251
|
+
- **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 still works, but the image then reports a pid of its own from `getpid()`.
|
|
252
|
+
- **WASIX:** `proc_exec` does this by itself.
|
|
253
|
+
|
|
247
254
|
### `/proc`
|
|
248
255
|
|
|
249
256
|
Every process of the kernel has `/proc/<pid>/` with `cmdline`, `comm`, `stat`, `statm` and `status`, in the formats procps reads, and `/proc/self/` has the same files for the process that reads them. 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`. 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
|
@@ -6299,8 +6299,9 @@ var WasmProcess = class {
|
|
|
6299
6299
|
case "proc-fork":
|
|
6300
6300
|
return { ok: true, kind: "json", json: await this.children.fork(req.state) };
|
|
6301
6301
|
case "proc-spawn": {
|
|
6302
|
-
const { file, argv, env, cwd, stdio, inherit } = req;
|
|
6303
|
-
const
|
|
6302
|
+
const { file, argv, env, cwd, stdio, inherit, exec } = req;
|
|
6303
|
+
const spawned = { file, argv, env, cwd, ...exec ? { exec } : {} };
|
|
6304
|
+
const pid = await this.children.spawn(spawned, stdio, inherit);
|
|
6304
6305
|
return { ok: true, kind: "json", json: pid };
|
|
6305
6306
|
}
|
|
6306
6307
|
case "proc-wait": {
|
|
@@ -6567,7 +6568,7 @@ function spawnWasmProcess(opts) {
|
|
|
6567
6568
|
});
|
|
6568
6569
|
const tinit = {
|
|
6569
6570
|
type: WASM_THREAD_INIT,
|
|
6570
|
-
pid: opts.pid,
|
|
6571
|
+
pid: opts.shownPid ?? opts.pid,
|
|
6571
6572
|
program: opts.program,
|
|
6572
6573
|
argv0: opts.argv0,
|
|
6573
6574
|
args: opts.args,
|
|
@@ -6581,7 +6582,7 @@ function spawnWasmProcess(opts) {
|
|
|
6581
6582
|
};
|
|
6582
6583
|
const init = {
|
|
6583
6584
|
type: WASM_PROCESS_INIT,
|
|
6584
|
-
pid: opts.pid,
|
|
6585
|
+
pid: opts.shownPid ?? opts.pid,
|
|
6585
6586
|
program: opts.program,
|
|
6586
6587
|
argv0: opts.argv0,
|
|
6587
6588
|
args: opts.args,
|
|
@@ -6631,12 +6632,22 @@ var JobTable = class {
|
|
|
6631
6632
|
remove(pid) {
|
|
6632
6633
|
this.members.delete(pid);
|
|
6633
6634
|
}
|
|
6634
|
-
exec(pid, child) {
|
|
6635
|
+
exec(pid, child, adopt = false) {
|
|
6635
6636
|
const member = this.members.get(child);
|
|
6637
|
+
if (member && adopt) member.shownAs = this.shown(pid);
|
|
6636
6638
|
if (member) member.execParent = pid;
|
|
6637
6639
|
const execer = this.members.get(pid);
|
|
6638
6640
|
if (execer) execer.execed = true;
|
|
6639
6641
|
}
|
|
6642
|
+
shown(pid) {
|
|
6643
|
+
let member = this.members.get(pid);
|
|
6644
|
+
for (let up = member; up; up = this.members.get(up.execParent ?? -1)) member = up;
|
|
6645
|
+
return member?.pid ?? pid;
|
|
6646
|
+
}
|
|
6647
|
+
shownParent(pid) {
|
|
6648
|
+
const parent = this.members.get(this.shown(pid))?.ppid;
|
|
6649
|
+
return parent === void 0 ? void 0 : this.shown(parent);
|
|
6650
|
+
}
|
|
6640
6651
|
pgidOf(pid) {
|
|
6641
6652
|
return this.members.get(pid)?.pgid;
|
|
6642
6653
|
}
|
|
@@ -6645,34 +6656,46 @@ var JobTable = class {
|
|
|
6645
6656
|
if (!member) throw new KernelError("ESRCH");
|
|
6646
6657
|
return member;
|
|
6647
6658
|
}
|
|
6659
|
+
idOf(pid) {
|
|
6660
|
+
return this.members.get(pid)?.shownAs ?? pid;
|
|
6661
|
+
}
|
|
6662
|
+
byId(id) {
|
|
6663
|
+
for (const member of this.members.values()) if (member.shownAs === id) return member;
|
|
6664
|
+
return this.member(id);
|
|
6665
|
+
}
|
|
6648
6666
|
setpgid(caller, pid, pgid) {
|
|
6649
|
-
const
|
|
6650
|
-
const
|
|
6667
|
+
const me = this.idOf(caller);
|
|
6668
|
+
const target = this.byId(pid || me);
|
|
6669
|
+
const id = this.idOf(target.pid);
|
|
6670
|
+
const group = pgid || id;
|
|
6651
6671
|
if (group < 0) throw new KernelError("EINVAL");
|
|
6652
6672
|
const self = this.member(caller);
|
|
6653
|
-
if (
|
|
6654
|
-
if (target.ppid
|
|
6673
|
+
if (id !== me) {
|
|
6674
|
+
if (target.ppid === void 0 || this.idOf(target.ppid) !== me) {
|
|
6675
|
+
throw new KernelError("ESRCH");
|
|
6676
|
+
}
|
|
6655
6677
|
if (target.execed) throw new KernelError("EACCES");
|
|
6656
6678
|
}
|
|
6657
6679
|
if (target.sid !== self.sid) throw new KernelError("EPERM");
|
|
6658
|
-
if (
|
|
6680
|
+
if (id === target.sid) throw new KernelError("EPERM");
|
|
6659
6681
|
const exists = [...this.members.values()].some((m) => m.pgid === group && m.sid === target.sid);
|
|
6660
|
-
if (group !==
|
|
6682
|
+
if (group !== id && !exists) throw new KernelError("EPERM");
|
|
6661
6683
|
target.pgid = group;
|
|
6662
6684
|
}
|
|
6663
6685
|
getpgid(caller, pid) {
|
|
6664
|
-
return this.
|
|
6686
|
+
return this.byId(pid || this.idOf(caller)).pgid;
|
|
6665
6687
|
}
|
|
6666
6688
|
getsid(caller, pid) {
|
|
6667
|
-
return this.
|
|
6689
|
+
return this.byId(pid || this.idOf(caller)).sid;
|
|
6668
6690
|
}
|
|
6669
6691
|
setsid(pid) {
|
|
6670
6692
|
const member = this.member(pid);
|
|
6671
|
-
|
|
6672
|
-
member.
|
|
6673
|
-
member.
|
|
6674
|
-
|
|
6675
|
-
|
|
6693
|
+
const id = this.idOf(pid);
|
|
6694
|
+
if (member.pgid === id) throw new KernelError("EPERM");
|
|
6695
|
+
member.sid = id;
|
|
6696
|
+
member.pgid = id;
|
|
6697
|
+
this.terminals.delete(id);
|
|
6698
|
+
return id;
|
|
6676
6699
|
}
|
|
6677
6700
|
terminalNamed(name2) {
|
|
6678
6701
|
const known = /* @__PURE__ */ new Set([...this.terminals.values(), ...this.foreground.keys()]);
|
|
@@ -6684,9 +6707,10 @@ var JobTable = class {
|
|
|
6684
6707
|
}
|
|
6685
6708
|
acquireTerminal(pid, tty) {
|
|
6686
6709
|
const member = this.members.get(pid);
|
|
6687
|
-
|
|
6710
|
+
const id = this.idOf(pid);
|
|
6711
|
+
if (!member || member.sid !== id || this.terminals.has(id)) return false;
|
|
6688
6712
|
if ([...this.terminals.values()].includes(tty)) return false;
|
|
6689
|
-
this.terminals.set(
|
|
6713
|
+
this.terminals.set(id, tty);
|
|
6690
6714
|
this.foreground.set(tty, member.pgid);
|
|
6691
6715
|
return true;
|
|
6692
6716
|
}
|
|
@@ -8022,10 +8046,11 @@ var Launcher = class {
|
|
|
8022
8046
|
locks: this.locks,
|
|
8023
8047
|
onReap: (child) => this.reaped(child),
|
|
8024
8048
|
...req.fork ? { fork: req.fork } : {},
|
|
8025
|
-
...
|
|
8049
|
+
...this.shownIds(req)
|
|
8026
8050
|
});
|
|
8027
8051
|
this.processes.set(pid, handle);
|
|
8028
8052
|
this.jobs.add(pid, req.ppid, (sig) => handle.signal(sig), terminal);
|
|
8053
|
+
if (req.exec && req.ppid !== void 0) this.jobs.exec(req.ppid, pid, true);
|
|
8029
8054
|
this.described.set(pid, {
|
|
8030
8055
|
argv: [req.argv0, ...req.args],
|
|
8031
8056
|
tty: terminal?.name ?? null,
|
|
@@ -8038,6 +8063,12 @@ var Launcher = class {
|
|
|
8038
8063
|
});
|
|
8039
8064
|
return handle;
|
|
8040
8065
|
}
|
|
8066
|
+
shownIds(req) {
|
|
8067
|
+
if (req.ppid === void 0) return {};
|
|
8068
|
+
if (!req.exec) return { ppid: this.jobs.shown(req.ppid) };
|
|
8069
|
+
const ppid = this.jobs.shownParent(req.ppid);
|
|
8070
|
+
return { shownPid: this.jobs.shown(req.ppid), ...ppid !== void 0 ? { ppid } : {} };
|
|
8071
|
+
}
|
|
8041
8072
|
forget(pid) {
|
|
8042
8073
|
this.jobs.remove(pid);
|
|
8043
8074
|
this.described.delete(pid);
|
|
@@ -8085,12 +8116,21 @@ var Launcher = class {
|
|
|
8085
8116
|
await fds.closeAll();
|
|
8086
8117
|
throw new SpawnError(await this.unrunnable(req.file, req.cwd));
|
|
8087
8118
|
}
|
|
8088
|
-
const
|
|
8119
|
+
const exec = req.exec ? { exec: true } : {};
|
|
8120
|
+
const handle = await this.launch(planned, {
|
|
8121
|
+
env: req.env,
|
|
8122
|
+
cwd: req.cwd,
|
|
8123
|
+
fds,
|
|
8124
|
+
report,
|
|
8125
|
+
ppid,
|
|
8126
|
+
...exec
|
|
8127
|
+
});
|
|
8089
8128
|
return childHandle(handle);
|
|
8090
8129
|
};
|
|
8091
8130
|
}
|
|
8092
8131
|
forker(ppid, parent) {
|
|
8093
|
-
|
|
8132
|
+
const { exec: _exec, ...image } = parent;
|
|
8133
|
+
return async (state, fds) => childHandle(this.start({ ...image, cwd: state.cwd ?? parent.cwd, fds, ppid, fork: state }));
|
|
8094
8134
|
}
|
|
8095
8135
|
kill(pid, sig) {
|
|
8096
8136
|
if (pid < 0) return this.jobs.killGroup(-pid, sig);
|