@ai-ecoverse/slicc-kernel 1.112.0 → 1.114.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.
@@ -993,6 +993,8 @@ var S_ISGID2 = 1024;
993
993
  var READ_ATTEMPTS = 3;
994
994
  var MAX_LINKS2 = 40;
995
995
  var CHECK_MS = 1e3;
996
+ var ABSENT_MS = 2;
997
+ var ABSENT_NAMES = 4096;
996
998
  var FILE_HANDLES = 4096;
997
999
  var STALE = /* @__PURE__ */ new Set(["NotFoundError", "TypeMismatchError"]);
998
1000
  var EXECUTABLE = /\/node_modules\/(?:@[^/]+\/)?[^/]+\/bin\//;
@@ -1127,6 +1129,8 @@ var OpfsFs = class {
1127
1129
  meta;
1128
1130
  dirs = new PathMap();
1129
1131
  files = new PathMap();
1132
+ absent = new PathMap();
1133
+ changes = 0;
1130
1134
  snapshots = /* @__PURE__ */ new WeakMap();
1131
1135
  found = /* @__PURE__ */ new WeakMap();
1132
1136
  checked = /* @__PURE__ */ new WeakMap();
@@ -1365,8 +1369,14 @@ var OpfsFs = class {
1365
1369
  return true;
1366
1370
  }
1367
1371
  forget(path) {
1372
+ this.changes++;
1368
1373
  this.dirs.deleteTree(path);
1369
1374
  this.files.deleteTree(path);
1375
+ this.absent.deleteTree(path);
1376
+ }
1377
+ missed(path) {
1378
+ if (this.absent.size >= ABSENT_NAMES) this.absent.clear();
1379
+ this.absent.set(path, performance.now());
1370
1380
  }
1371
1381
  remember(path, handle, looked = false) {
1372
1382
  if (handle.kind !== "file") return handle;
@@ -1416,8 +1426,15 @@ var OpfsFs = class {
1416
1426
  this.snapshots.delete(cached);
1417
1427
  }
1418
1428
  }
1429
+ const kept = this.dirs.get(path);
1430
+ if (kept && await this.current(path, kept)) return kept;
1431
+ const gone = this.absent.get(path);
1432
+ if (gone !== void 0 && performance.now() - gone < ABSENT_MS) {
1433
+ throw translate({ name: "NotFoundError" }, path);
1434
+ }
1435
+ const seen = this.changes;
1419
1436
  const [dir, name2] = await this.parent(path);
1420
- const known = this.dirs.has(path);
1437
+ const known = kept !== void 0;
1421
1438
  return this.inDir(dir, async (parent) => {
1422
1439
  const [first, second] = known ? ["directory", "file"] : ["file", "directory"];
1423
1440
  try {
@@ -1427,7 +1444,9 @@ var OpfsFs = class {
1427
1444
  }
1428
1445
  return this.remember(path, await this.child(parent, name2, second), true);
1429
1446
  }).catch((err) => {
1430
- throw translate(err, path);
1447
+ const error = translate(err, path);
1448
+ if (error.code === "ENOENT" && seen === this.changes) this.missed(path);
1449
+ throw error;
1431
1450
  });
1432
1451
  }
1433
1452
  real(path) {
@@ -1554,7 +1573,9 @@ var OpfsFs = class {
1554
1573
  }
1555
1574
  flushing = {};
1556
1575
  touch(now, ...dirs) {
1576
+ this.changes++;
1557
1577
  for (const dir of dirs) {
1578
+ this.absent.deleteTree(dir);
1558
1579
  this.dirTimes.set(dir, now);
1559
1580
  this.dirDirty.add(dir);
1560
1581
  }
@@ -4941,6 +4962,14 @@ var SIGNAL_BY_NAME = {
4941
4962
  SIGSTOP: SIG.STOP,
4942
4963
  SIGCONT: SIG.CONT
4943
4964
  };
4965
+ var SI = { USER: 0, QUEUE: -1, TIMER: -2, TKILL: -6, KERNEL: 128 };
4966
+ var CLD = { EXITED: 1, KILLED: 2, DUMPED: 3, STOPPED: 5, CONTINUED: 6 };
4967
+ var KERNEL_SIGINFO = Object.freeze({
4968
+ code: SI.KERNEL,
4969
+ pid: 0,
4970
+ uid: 0,
4971
+ status: 0
4972
+ });
4944
4973
 
4945
4974
  // src/body-idle.ts
4946
4975
  var BODY_IDLE_MS = 5 * 60 * 1e3;
@@ -6192,7 +6221,7 @@ function satisfies(version, range2) {
6192
6221
  }
6193
6222
 
6194
6223
  // src/version.ts
6195
- var KERNEL_VERSION = true ? "1.112.0" : "0.0.0-dev";
6224
+ var KERNEL_VERSION = true ? "1.114.0" : "0.0.0-dev";
6196
6225
  var OS_RELEASE = "6.0.0-slicc";
6197
6226
  function procVersion() {
6198
6227
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -9068,8 +9097,16 @@ var ChildTable = class {
9068
9097
  void handle.exited.then((code) => {
9069
9098
  child.code = code;
9070
9099
  this.watchers.delete(handle.pid);
9100
+ const termsig = handle.termsig?.();
9071
9101
  if (!this.kept.delete(handle.pid) && this.autoReap?.()) this.reap(handle.pid, code);
9072
- this.onChildState?.();
9102
+ const uid = handle.uid?.();
9103
+ this.onChildState?.({
9104
+ pid: handle.pid,
9105
+ state: "exited",
9106
+ status: termsig ?? code,
9107
+ termsig,
9108
+ uid
9109
+ });
9073
9110
  });
9074
9111
  handle.onState?.((state, sig) => {
9075
9112
  child.stopReport = state === "stopped" ? sig : void 0;
@@ -9079,7 +9116,7 @@ var ChildTable = class {
9079
9116
  const waiters = this.stateChanged;
9080
9117
  this.stateChanged = [];
9081
9118
  for (const wake of waiters) wake();
9082
- this.onChildState?.();
9119
+ this.onChildState?.({ pid: handle.pid, state, status: sig, uid: handle.uid?.() });
9083
9120
  });
9084
9121
  this.children.set(handle.pid, child);
9085
9122
  return handle.pid;
@@ -17149,6 +17186,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
17149
17186
  "sig-mask",
17150
17187
  "sig-inherited",
17151
17188
  "sig-waiting",
17189
+ "sig-info",
17152
17190
  "sig-pause",
17153
17191
  ...SOCKET_OPS,
17154
17192
  ...EPOLL_OPS,
@@ -17230,7 +17268,7 @@ var WasmProcess = class {
17230
17268
  this.children = new ChildTable(fds, options.spawner, options.forker);
17231
17269
  this.nodes = options.nodes ?? new VfsNodes(options.fs);
17232
17270
  if (!options.nodes) options.openFiles?.add(this.nodes);
17233
- this.children.onChildState = () => this.signal(SIG.CHLD);
17271
+ this.children.onChildState = (child) => this.signal(SIG.CHLD, child && this.childInfo(child));
17234
17272
  this.children.autoReap = () => this.reapsChildren();
17235
17273
  this.seedDl(options.dl);
17236
17274
  this.children.onReap = (pid2) => {
@@ -17247,10 +17285,43 @@ var WasmProcess = class {
17247
17285
  inheritable(fork = false) {
17248
17286
  return ((fork ? 0 : this.ignored) | this.inherited) & ~this.caught;
17249
17287
  }
17250
- signal(sig) {
17288
+ sigInfos = /* @__PURE__ */ new Map();
17289
+ signal(sig, info) {
17290
+ const pending = ((this.options.pendingBits?.() ?? 0) & sigbit(sig)) !== 0;
17291
+ const outcome = this.signalOutcome(sig, info);
17292
+ if (outcome === "deliver" && !(pending && this.sigInfos.has(`0:${sig}`))) {
17293
+ this.sigInfos.set(`0:${sig}`, info ?? KERNEL_SIGINFO);
17294
+ }
17295
+ return outcome;
17296
+ }
17297
+ async threadKill(tid, sig) {
17298
+ const info = await this.threadSender(sig);
17299
+ if (this.options.threadKill?.(tid, sig)) this.sigInfos.set(`${tid}:${sig}`, info);
17300
+ else this.options.raise?.(sig, info);
17301
+ }
17302
+ async threadSender(sig) {
17303
+ const pid = (await this.options.identity?.())?.pid ?? this.pid;
17304
+ const code = sig === SIG.PIPE ? SI.USER : SI.TKILL;
17305
+ return { code, pid, uid: this.cred.ruid, status: 0 };
17306
+ }
17307
+ childInfo(child) {
17308
+ const code = child.state === "stopped" ? CLD.STOPPED : child.state === "continued" ? CLD.CONTINUED : child.termsig ? CLD.KILLED : CLD.EXITED;
17309
+ return { code, pid: child.pid, uid: child.uid ?? this.cred.ruid, status: child.status };
17310
+ }
17311
+ takeSigInfo(sig, tid) {
17312
+ for (const key of [`${tid}:${sig}`, `0:${sig}`]) {
17313
+ const info = this.sigInfos.get(key);
17314
+ if (info) {
17315
+ this.sigInfos.delete(key);
17316
+ return info;
17317
+ }
17318
+ }
17319
+ return null;
17320
+ }
17321
+ signalOutcome(sig, info) {
17251
17322
  if (this.execChild !== void 0) {
17252
17323
  if (sig === SIG.CONT) this.cont();
17253
- void Promise.resolve(this.options.kill?.(this.execChild, sig)).catch(() => void 0);
17324
+ void Promise.resolve(this.options.kill?.(this.execChild, sig, info)).catch(() => void 0);
17254
17325
  if (sig !== SIG.KILL) return "forward";
17255
17326
  if (!this.options.writesBack?.(this.execChild)) return "terminate";
17256
17327
  this.wake?.();
@@ -18311,8 +18382,10 @@ var WasmProcess = class {
18311
18382
  case "sig-pause":
18312
18383
  return this.pause(cancelled);
18313
18384
  case "thread-kill":
18314
- if (!this.options.threadKill?.(req.tid, req.sig)) this.options.raise?.(req.sig);
18385
+ await this.threadKill(req.tid, req.sig);
18315
18386
  return { ok: true, kind: "void" };
18387
+ case "sig-info":
18388
+ return { ok: true, kind: "json", json: this.takeSigInfo(req.sig, req.tid ?? 0) };
18316
18389
  case "proc-captured":
18317
18390
  return { ok: true, kind: "bytes", bytes: this.children.captured(req.pid, req.slot) };
18318
18391
  case "proc-sudo":
@@ -18791,7 +18864,7 @@ function spawnWasmProcess(opts) {
18791
18864
  opts,
18792
18865
  header3,
18793
18866
  {
18794
- raise: (sig) => signal(sig),
18867
+ raise: (sig, info) => signal(sig, info),
18795
18868
  threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig),
18796
18869
  unblockedThread: (sig) => unblockedThread(threadSignals, sig),
18797
18870
  ...opts.program.abi === "js" ? {
@@ -18913,8 +18986,9 @@ function spawnWasmProcess(opts) {
18913
18986
  if (opts.program.abi !== "wasi" || done4) finish(code, sig);
18914
18987
  else dying.start(code, sig, header3, process, () => finish(code, sig));
18915
18988
  };
18916
- const signal = (sig) => {
18917
- if (process.signal(sig) === "terminate") terminate(sig === SIG.KILL ? 137 : 128 + sig, sig);
18989
+ const signal = (sig, info) => {
18990
+ if (process.signal(sig, info) === "terminate")
18991
+ terminate(sig === SIG.KILL ? 137 : 128 + sig, sig);
18918
18992
  };
18919
18993
  const kill = (code = 137) => finish(code, code > 128 && code < 160 ? code - 128 : void 0);
18920
18994
  return {
@@ -19084,14 +19158,14 @@ var JobTable = class {
19084
19158
  this.foreground.set(tty, member.pgid);
19085
19159
  return true;
19086
19160
  }
19087
- killGroup(pgid, sig, may = () => true) {
19161
+ killGroup(pgid, sig, may = () => true, info) {
19088
19162
  const group = [...this.members.values()].filter((m) => m.pgid === pgid);
19089
19163
  const targets = group.filter((m) => may(m.pid));
19090
19164
  if (targets.length === 0 && group.length > 0) throw new KernelError("EPERM");
19091
19165
  const pids = new Set(targets.map((m) => m.pid));
19092
19166
  if (sig !== 0) {
19093
19167
  for (const m of targets)
19094
- if (m.execParent === void 0 || !pids.has(m.execParent)) m.signal(sig);
19168
+ if (m.execParent === void 0 || !pids.has(m.execParent)) m.signal(sig, info);
19095
19169
  }
19096
19170
  return targets.length > 0;
19097
19171
  }
@@ -22362,7 +22436,8 @@ function childHandle(handle) {
22362
22436
  pid: handle.pid,
22363
22437
  exited: handle.exited,
22364
22438
  termsig: handle.termsig,
22365
- onState: (listener) => handle.onState(listener)
22439
+ onState: (listener) => handle.onState(listener),
22440
+ uid: () => handle.cred?.().ruid
22366
22441
  };
22367
22442
  }
22368
22443
  function concat7(chunks) {
@@ -23400,7 +23475,7 @@ var Launcher = class {
23400
23475
  onError: req.report,
23401
23476
  spawner: this.spawner(pid, req.report),
23402
23477
  forker: this.forker(pid, req),
23403
- kill: (target, sig) => this.kill(target, sig, this.credOf(pid), pid),
23478
+ kill: (target, sig, info) => this.kill(target, sig, this.credOf(pid), pid, info),
23404
23479
  writesBack: (target) => this.processes.get(target)?.writesBack() === true,
23405
23480
  processes: () => ({
23406
23481
  boot: this.boot,
@@ -23435,7 +23510,7 @@ var Launcher = class {
23435
23510
  this.creds.set(pid, () => handle.cred?.() ?? copyCred(cred));
23436
23511
  this.marks(pid, req);
23437
23512
  if (req.ppid !== void 0 && this.controlsJobs(req.ppid)) this.settling.started(pid, req.ppid);
23438
- this.jobs.add(pid, req.ppid, (sig) => handle.signal(sig), terminal);
23513
+ this.jobs.add(pid, req.ppid, (sig, info) => handle.signal(sig, info), terminal);
23439
23514
  if (req.exec && req.ppid !== void 0) this.jobs.exec(req.ppid, pid, true);
23440
23515
  if (req.pgid !== void 0) this.jobs.join(pid, req.pgid);
23441
23516
  if (req.group === "lead") this.jobs.lead(pid);
@@ -23816,21 +23891,26 @@ var Launcher = class {
23816
23891
  ignoredBy(pid, fork = false) {
23817
23892
  return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
23818
23893
  }
23819
- kill(pid, sig, sender, from) {
23894
+ kill(pid, sig, sender, from, forwarded) {
23895
+ const info = forwarded ?? this.senderInfo(sender, from);
23820
23896
  const session = from === void 0 ? void 0 : this.jobs.sidOf(from);
23821
23897
  const may = (target) => !sender || maySignal(sender, this.credOf(target)) || sig === SIG.CONT && session !== void 0 && this.jobs.sidOf(target) === session || from !== void 0 && this.imageOf(from) === this.imageOf(target) || from !== void 0 && this.granted.get(this.jobs.shown(target)) === from || from !== void 0 && this.granted.get(this.jobs.pgidOf(target) ?? 0) === from;
23822
23898
  if (pid === -1) {
23823
23899
  const sender2 = from === void 0 ? void 0 : this.imageOf(from);
23824
- return this.killAll(sig, (member) => this.imageOf(member) !== sender2, may);
23900
+ return this.killAll(sig, (member) => this.imageOf(member) !== sender2, may, info);
23825
23901
  }
23826
- if (pid < 0) return this.jobs.killGroup(-pid, sig, (member) => may(this.imageOf(member)));
23902
+ if (pid < 0) return this.jobs.killGroup(-pid, sig, (member) => may(this.imageOf(member)), info);
23827
23903
  const handle = this.processes.get(pid);
23828
23904
  if (!handle) return false;
23829
23905
  if (!may(this.imageOf(pid))) throw fsError("EPERM", `pid ${pid}`);
23830
- if (sig !== 0) handle.signal(sig);
23906
+ if (sig !== 0) handle.signal(sig, info);
23831
23907
  return true;
23832
23908
  }
23833
- killAll(sig, other, may) {
23909
+ senderInfo(sender, from) {
23910
+ if (from === void 0) return void 0;
23911
+ return { code: SI.USER, pid: this.jobs.shown(from), uid: sender?.ruid ?? 0, status: 0 };
23912
+ }
23913
+ killAll(sig, other, may, info) {
23834
23914
  const candidates = [...this.processes].filter(([pid]) => pid !== 1 && other(pid));
23835
23915
  const targets = candidates.filter(([pid]) => may(this.imageOf(pid)));
23836
23916
  if (targets.length === 0 && candidates.length > 0) throw fsError("EPERM", "kill -1");
@@ -23838,7 +23918,7 @@ var Launcher = class {
23838
23918
  const parents = new Map(this.jobs.list().map((m) => [m.pid, m.execParent]));
23839
23919
  for (const [pid, handle] of targets) {
23840
23920
  const parent = parents.get(pid);
23841
- if (sig !== 0 && (parent === void 0 || !pids.has(parent))) handle.signal(sig);
23921
+ if (sig !== 0 && (parent === void 0 || !pids.has(parent))) handle.signal(sig, info);
23842
23922
  }
23843
23923
  return targets.length > 0;
23844
23924
  }