@ai-ecoverse/slicc-kernel 1.54.7 → 1.54.8
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 +1 -1
- package/dist/kernel-worker.js +33 -15
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +51 -26
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +33 -15
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +68 -43
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -500,7 +500,7 @@ Programs ask the kernel for their ids:
|
|
|
500
500
|
|
|
501
501
|
### `/proc`
|
|
502
502
|
|
|
503
|
-
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 are the credentials in `status` (`Uid:`, `Gid:`, `Groups:`) and 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. A process that isn't root sees only its own user's processes (see [Users](#users)). WASI and WASIX programs see the same `/proc`, read-only (opening a file in it for writing fails with `EROFS`), from every thread, also through a symlink that points into it (where every change, `mkdir`, `rename`, `unlink`, `chmod` and so on, fails too: with `EROFS` when the root file system has a physical `/proc`, which stays hidden and untouched, and otherwise with the `ENOENT` of the missing directory, since that check is only paid for when a physical `/proc` exists), and `/` lists it, so a WASI program gets a preopen for it; `/proc/self` is the program's own pid there too (the pid an exec'd program took over). Neither has `/proc/<pid>/fd` yet.
|
|
503
|
+
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 are the credentials in `status` (`Uid:`, `Gid:`, `Groups:`) and 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. A process that isn't root sees only its own user's processes (see [Users](#users)). WASI and WASIX programs see the same `/proc`, read-only (opening a file in it for writing fails with `EROFS`), from every thread, also through a symlink that points into it (where every change, `mkdir`, `rename`, `unlink`, `chmod` and so on, fails too: with `EROFS` when the root file system has a physical `/proc`, which stays hidden and untouched, and otherwise with the `ENOENT` of the missing directory, since that check is only paid for when a physical `/proc` exists; with one, a symlink whose target passes `..` after a file or a missing name, such as `/f/../proc`, fails with `ENOTDIR` or `ENOENT`, as on Linux), and `/` lists it, so a WASI program gets a preopen for it; `/proc/self` is the program's own pid there too (the pid an exec'd program took over). Neither has `/proc/<pid>/fd` yet.
|
|
504
504
|
|
|
505
505
|
The kernel writes `/etc/passwd` and `/etc/group` when it starts (see [Users](#users)). While the root has none of them, or no `/etc/mtab`, reading them gets per-process ones: root is uid 0 and the realm user, uid 1000, is named after `USER`, or `web_user` (Emscripten's default) without one, so it matches `$USER`, with `HOME` as its home, so `id`, `whoami`, `ls -l` and `ps` show names. Nothing is written to OPFS, and a real file there wins.
|
|
506
506
|
|
package/dist/kernel-worker.js
CHANGED
|
@@ -1806,9 +1806,9 @@ var KernelSocket = class _KernelSocket {
|
|
|
1806
1806
|
case SO_TYPE:
|
|
1807
1807
|
return SOCK_STREAM;
|
|
1808
1808
|
case SO_ERROR: {
|
|
1809
|
-
const
|
|
1809
|
+
const failed2 = this.failed;
|
|
1810
1810
|
this.failed = void 0;
|
|
1811
|
-
return
|
|
1811
|
+
return failed2 ? wasiErrno(failed2) : 0;
|
|
1812
1812
|
}
|
|
1813
1813
|
case SO_ACCEPTCONN:
|
|
1814
1814
|
return this.state === "listening" ? 1 : 0;
|
|
@@ -8022,6 +8022,7 @@ function* procWalk(path, follow2) {
|
|
|
8022
8022
|
let done4 = [];
|
|
8023
8023
|
let todo = path.split("/").filter((part) => part !== "");
|
|
8024
8024
|
let hops = 0;
|
|
8025
|
+
let broken;
|
|
8025
8026
|
while (todo.length > 0) {
|
|
8026
8027
|
const part = todo.shift();
|
|
8027
8028
|
if (part === ".") continue;
|
|
@@ -8031,19 +8032,31 @@ function* procWalk(path, follow2) {
|
|
|
8031
8032
|
}
|
|
8032
8033
|
const at = `/${[...done4, part].join("/")}`;
|
|
8033
8034
|
const whole = normalize(`/${[...done4, part, ...todo].join("/")}`);
|
|
8034
|
-
if (inProc(at) && inProc(whole)) return whole;
|
|
8035
|
+
if (inProc(at) && inProc(whole)) return broken ?? whole;
|
|
8035
8036
|
if (!follow2 && todo.length === 0) return void 0;
|
|
8036
|
-
const target = yield at;
|
|
8037
|
-
if (target ===
|
|
8038
|
-
if (target === void 0) done4.push(part);
|
|
8039
|
-
else {
|
|
8037
|
+
const target = yield { at, check: todo.find((next2) => next2 !== ".") === ".." };
|
|
8038
|
+
if (typeof target === "string") {
|
|
8040
8039
|
if (++hops > MAX_HOPS2) return void 0;
|
|
8041
|
-
|
|
8042
|
-
|
|
8040
|
+
[done4, todo] = throughLink(target, done4, todo);
|
|
8041
|
+
} else {
|
|
8042
|
+
broken ??= refusalOf(target);
|
|
8043
|
+
done4.push(part);
|
|
8043
8044
|
}
|
|
8044
8045
|
}
|
|
8045
8046
|
return void 0;
|
|
8046
8047
|
}
|
|
8048
|
+
function failed(err) {
|
|
8049
|
+
const code = err?.code;
|
|
8050
|
+
return { refused: typeof code === "string" ? code : "ENOENT" };
|
|
8051
|
+
}
|
|
8052
|
+
function refusalOf(found) {
|
|
8053
|
+
if (found === true) return void 0;
|
|
8054
|
+
return found === false ? { refused: "ENOTDIR" } : found;
|
|
8055
|
+
}
|
|
8056
|
+
function throughLink(target, done4, todo) {
|
|
8057
|
+
const parts = target.split("/").filter((part) => part !== "");
|
|
8058
|
+
return [target.startsWith("/") ? [] : done4, [...parts, ...todo]];
|
|
8059
|
+
}
|
|
8047
8060
|
async function procAlias(fs, path, follow2) {
|
|
8048
8061
|
const { readlink, lstat } = fs;
|
|
8049
8062
|
if (!readlink || !lstat) return void 0;
|
|
@@ -8055,7 +8068,10 @@ async function procAlias(fs, path, follow2) {
|
|
|
8055
8068
|
const walk = procWalk(path, follow2);
|
|
8056
8069
|
let step = walk.next();
|
|
8057
8070
|
while (!step.done) {
|
|
8058
|
-
const
|
|
8071
|
+
const { at, check } = step.value;
|
|
8072
|
+
const link2 = await readlink.call(fs, at).catch(() => void 0);
|
|
8073
|
+
const isDir = (st) => st.isDirectory === true;
|
|
8074
|
+
const target = link2 ?? (check ? await lstat.call(fs, at).then(isDir, failed) : true);
|
|
8059
8075
|
step = walk.next(target);
|
|
8060
8076
|
}
|
|
8061
8077
|
return step.value;
|
|
@@ -10101,6 +10117,8 @@ var WasmProcess = class {
|
|
|
10101
10117
|
async openVfs(req) {
|
|
10102
10118
|
if (inProc(req.path)) return this.openProc(req, req.path);
|
|
10103
10119
|
const alias = req.orphan ? void 0 : await procAlias(this.options.fs, req.path, !req.exclusive);
|
|
10120
|
+
if (typeof alias === "object")
|
|
10121
|
+
throw Object.assign(new Error(alias.refused), { code: alias.refused });
|
|
10104
10122
|
if (alias !== void 0) return this.openProc(req, alias);
|
|
10105
10123
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
10106
10124
|
const fd = this.fds.install(heldFile(), 3);
|
|
@@ -11757,22 +11775,22 @@ async function mountFstab(lines2, mount, signal, retries = FSTAB_RETRIES, discar
|
|
|
11757
11775
|
);
|
|
11758
11776
|
}
|
|
11759
11777
|
async function mountLine({ line, spec, invalid }, mount, signal, retries, discard) {
|
|
11760
|
-
let
|
|
11778
|
+
let failed2 = invalid;
|
|
11761
11779
|
for (let attempt = 0; !invalid && attempt <= retries.length && !signal.aborted; attempt++) {
|
|
11762
11780
|
try {
|
|
11763
11781
|
const entry = await mount(spec);
|
|
11764
11782
|
if (!signal.aborted) return { line, target: spec.target, entry };
|
|
11765
11783
|
discard(entry);
|
|
11766
|
-
|
|
11784
|
+
failed2 = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
|
|
11767
11785
|
break;
|
|
11768
11786
|
} catch (err) {
|
|
11769
|
-
|
|
11787
|
+
failed2 = err;
|
|
11770
11788
|
if (FINAL.has(codeOf3(err)) || attempt === retries.length) break;
|
|
11771
11789
|
await wait(retries[attempt], signal);
|
|
11772
11790
|
}
|
|
11773
11791
|
}
|
|
11774
|
-
const code = codeOf3(
|
|
11775
|
-
return { line, target: spec.target, code, error: String(
|
|
11792
|
+
const code = codeOf3(failed2);
|
|
11793
|
+
return { line, target: spec.target, code, error: String(failed2?.message ?? code) };
|
|
11776
11794
|
}
|
|
11777
11795
|
|
|
11778
11796
|
// src/mount/hostfs.ts
|