@ai-ecoverse/slicc-kernel 1.46.0 → 1.47.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.
@@ -9419,6 +9419,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
9419
9419
  "proc-captured",
9420
9420
  "proc-fork",
9421
9421
  "proc-kill",
9422
+ "thread-kill",
9422
9423
  "proc-list",
9423
9424
  "mount-list",
9424
9425
  "mount",
@@ -9583,14 +9584,14 @@ var WasmProcess = class {
9583
9584
  if (isFdSyscall(req)) return await this.fdSyscall(req, cancelled);
9584
9585
  if (isTtySyscall(req)) return this.ttySyscall(req);
9585
9586
  if (isJobSyscall(req)) return this.jobSyscall(req);
9586
- if (isSocketSyscall(req)) return await this.socketSyscall(req);
9587
+ if (isSocketSyscall(req)) return await this.socketSyscall(req, cancelled);
9587
9588
  if (isHttpSyscall(req)) return await this.httpSyscall(req);
9588
9589
  if (isHostSyscall(req)) {
9589
9590
  return await hostSyscall(req, {
9590
9591
  pid: this.pid,
9591
9592
  locks: this.options.locks,
9592
9593
  ops: this.asyncOps,
9593
- blocking: () => this.blockingSignal(),
9594
+ blocking: () => this.blockingSignal(cancelled),
9594
9595
  valid: (inner) => isWasmSyscall(inner) && !isHostSyscall(inner)
9595
9596
  });
9596
9597
  }
@@ -9598,7 +9599,7 @@ var WasmProcess = class {
9598
9599
  const { ptys, jobs } = this.options;
9599
9600
  return ptySyscall(req, { pid: this.pid, fds: this.fds, ptys, jobs });
9600
9601
  }
9601
- return await this.procSyscall(req);
9602
+ return await this.procSyscall(req, cancelled);
9602
9603
  } catch (e) {
9603
9604
  if (e instanceof KernelError || e instanceof SpawnError) {
9604
9605
  return { ok: false, errno: e.code, message: e.code };
@@ -9613,11 +9614,11 @@ var WasmProcess = class {
9613
9614
  refuseIfPending(restart) {
9614
9615
  if (restart && this.options.hasPending?.()) throw new KernelError("EINTR");
9615
9616
  }
9616
- blockingSignal() {
9617
- if (this.options.hasPending?.()) throw new KernelError("EINTR");
9618
- return this.interrupt.signal;
9617
+ blockingSignal(cancelled) {
9618
+ if (this.options.hasPending?.() || cancelled?.aborted) throw new KernelError("EINTR");
9619
+ return cancelled ? AbortSignal.any([this.interrupt.signal, cancelled]) : this.interrupt.signal;
9619
9620
  }
9620
- async read(req) {
9621
+ async read(req, cancelled) {
9621
9622
  const file = this.fds.get(req.fd).file;
9622
9623
  const read = req.peek ? file.peek : file.read;
9623
9624
  if (!read) throw new KernelError(req.peek && file.read ? "EOPNOTSUPP" : "EBADF");
@@ -9626,15 +9627,15 @@ var WasmProcess = class {
9626
9627
  if (file instanceof KernelSocket && file.unconnected) throw new KernelError("ENOTCONN");
9627
9628
  const ready2 = pollFile(file).readable;
9628
9629
  if (!ready2 && req.nonblock) throw new KernelError("EAGAIN");
9629
- const signal = ready2 ? this.interrupt.signal : this.blockingSignal();
9630
+ const signal = ready2 ? this.interrupt.signal : this.blockingSignal(cancelled);
9630
9631
  return read.call(file, Math.max(0, Math.min(req.max, MAX_READ)), signal);
9631
9632
  }
9632
- async write(fd, body, nonblock = false) {
9633
+ async write(fd, body, nonblock = false, cancelled) {
9633
9634
  const file = this.fds.get(fd).file;
9634
9635
  if (!file.write) throw new KernelError("EBADF");
9635
9636
  if (!pollFile(file).writable) {
9636
9637
  if (nonblock) throw new KernelError("EAGAIN");
9637
- return file.write(body, this.blockingSignal());
9638
+ return file.write(body, this.blockingSignal(cancelled));
9638
9639
  }
9639
9640
  if (nonblock) return file.write(body, AbortSignal.abort());
9640
9641
  return file.write(
@@ -9689,9 +9690,13 @@ var WasmProcess = class {
9689
9690
  if (isVfsSyscall(req)) return this.vfsSyscall(req);
9690
9691
  switch (req.op) {
9691
9692
  case "fd-read":
9692
- return { ok: true, kind: "bytes", bytes: await this.read(req) };
9693
+ return { ok: true, kind: "bytes", bytes: await this.read(req, cancelled) };
9693
9694
  case "fd-write":
9694
- return { ok: true, kind: "json", json: await this.write(req.fd, req.body, req.nonblock) };
9695
+ return {
9696
+ ok: true,
9697
+ kind: "json",
9698
+ json: await this.write(req.fd, req.body, req.nonblock, cancelled)
9699
+ };
9695
9700
  case "fd-close":
9696
9701
  this.options.locks?.closed(this.pid, req.fd);
9697
9702
  await Promise.resolve(this.fds.close(req.fd));
@@ -9756,8 +9761,7 @@ var WasmProcess = class {
9756
9761
  return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
9757
9762
  case "fd-select": {
9758
9763
  const { read, write, timeoutMs } = req;
9759
- const blocking = this.blockingSignal();
9760
- const signal = cancelled ? AbortSignal.any([blocking, cancelled]) : blocking;
9764
+ const signal = this.blockingSignal(cancelled);
9761
9765
  const selected = await selectFds(this.fds, read, write, timeoutMs, signal);
9762
9766
  return { ok: true, kind: "json", json: selected };
9763
9767
  }
@@ -9927,13 +9931,13 @@ var WasmProcess = class {
9927
9931
  if (!http) return Promise.resolve({ ok: false, errno: "ENETUNREACH", message: NO_TRANSPORT });
9928
9932
  return http.syscall(req);
9929
9933
  }
9930
- socketSyscall(req) {
9934
+ socketSyscall(req, cancelled) {
9931
9935
  this.net ??= this.options.net ?? new LoopbackNet();
9932
9936
  const resolver = this.options.resolver ?? HOSTS_ONLY;
9933
9937
  return socketSyscall(req, {
9934
9938
  fds: this.fds,
9935
9939
  net: this.net,
9936
- blocking: () => this.blockingSignal(),
9940
+ blocking: () => this.blockingSignal(cancelled),
9937
9941
  resolve: (name2, family, blocking) => resolver.resolve(name2, family, blocking)
9938
9942
  });
9939
9943
  }
@@ -9943,7 +9947,7 @@ var WasmProcess = class {
9943
9947
  if (!tty) throw new KernelError("ENOTTY");
9944
9948
  return tty;
9945
9949
  }
9946
- async procSyscall(req) {
9950
+ async procSyscall(req, cancelled) {
9947
9951
  switch (req.op) {
9948
9952
  case "proc-fork":
9949
9953
  this.refuseIfPending(req.restart);
@@ -9952,7 +9956,7 @@ var WasmProcess = class {
9952
9956
  this.refuseIfPending(req.restart);
9953
9957
  return { ok: true, kind: "json", json: await this.spawn(req) };
9954
9958
  case "proc-wait": {
9955
- const signal = req.nohang ? this.interrupt.signal : this.blockingSignal();
9959
+ const signal = req.nohang ? this.interrupt.signal : this.blockingSignal(cancelled);
9956
9960
  const flags = {
9957
9961
  untraced: req.untraced,
9958
9962
  continued: req.continued,
@@ -10012,7 +10016,10 @@ var WasmProcess = class {
10012
10016
  this.inherited &= ~(req.defaults ?? 0);
10013
10017
  return { ok: true, kind: "void" };
10014
10018
  case "sig-pause":
10015
- return this.pause();
10019
+ return this.pause(cancelled);
10020
+ case "thread-kill":
10021
+ if (!this.options.threadKill?.(req.tid, req.sig)) this.options.raise?.(req.sig);
10022
+ return { ok: true, kind: "void" };
10016
10023
  case "proc-captured":
10017
10024
  return { ok: true, kind: "bytes", bytes: this.children.captured(req.pid, req.slot) };
10018
10025
  }
@@ -10034,8 +10041,8 @@ var WasmProcess = class {
10034
10041
  }
10035
10042
  return { ok: true, kind: "void" };
10036
10043
  }
10037
- pause() {
10038
- return aborted(this.blockingSignal());
10044
+ pause(cancelled) {
10045
+ return aborted(this.blockingSignal(cancelled));
10039
10046
  }
10040
10047
  alarm;
10041
10048
  dlLog = [];
@@ -10152,6 +10159,18 @@ var Dying = class {
10152
10159
  return [typeof reported === "number" ? reported : CRASHED, void 0];
10153
10160
  }
10154
10161
  };
10162
+ function killThread(thread, caught, sig) {
10163
+ if (!thread || (caught & sigbit(sig)) === 0) return false;
10164
+ Atomics.or(thread.header, SAB_I_SIGNALS, sigbit(sig));
10165
+ Atomics.notify(thread.header, SAB_I_SIGNALS);
10166
+ const blocked = thread.interrupt;
10167
+ thread.interrupt = new AbortController();
10168
+ blocked.abort();
10169
+ return true;
10170
+ }
10171
+ function threadCancel(thread) {
10172
+ return Atomics.load(thread.header, SAB_I_SIGNALS) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
10173
+ }
10155
10174
  function notifiers(header2) {
10156
10175
  return {
10157
10176
  onPending(sig) {
@@ -10234,10 +10253,8 @@ function holdingToken(opts, holds) {
10234
10253
  renamed: (from, to) => holds.renamed(from, to)
10235
10254
  });
10236
10255
  }
10237
- function spawnWasmProcess(opts) {
10238
- const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
10239
- const header2 = new Int32Array(sab, 0, SAB_HEADER_I32);
10240
- const process = new WasmProcess(opts.pid, opts.fds, {
10256
+ function processOptions(opts, header2, hooks) {
10257
+ return {
10241
10258
  ...inherited(opts),
10242
10259
  ...opts.identity ? { identity: opts.identity } : {},
10243
10260
  ...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
@@ -10262,9 +10279,23 @@ function spawnWasmProcess(opts) {
10262
10279
  ...notifiers(header2),
10263
10280
  onTimer: (which) => void Atomics.or(header2, SAB_I_TIMERS, 1 << which),
10264
10281
  hasPending: () => Atomics.load(header2, SAB_I_SIGNALS) !== 0 || Atomics.load(header2, SAB_I_TIMERS) !== 0,
10265
- raise: (sig) => signal(sig),
10282
+ raise: hooks.raise,
10283
+ threadKill: hooks.threadKill,
10266
10284
  ...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header2, SAB_I_SIGNALS) } : {}
10267
- });
10285
+ };
10286
+ }
10287
+ function spawnWasmProcess(opts) {
10288
+ const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
10289
+ const header2 = new Int32Array(sab, 0, SAB_HEADER_I32);
10290
+ const threadSignals = /* @__PURE__ */ new Map();
10291
+ const process = new WasmProcess(
10292
+ opts.pid,
10293
+ opts.fds,
10294
+ processOptions(opts, header2, {
10295
+ raise: (sig) => signal(sig),
10296
+ threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig)
10297
+ })
10298
+ );
10268
10299
  publishStops(process, header2);
10269
10300
  const holds = new HeldPaths();
10270
10301
  opts.held?.add(holds);
@@ -10331,7 +10362,15 @@ function spawnWasmProcess(opts) {
10331
10362
  }
10332
10363
  const tsab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
10333
10364
  const tw = opts.createWorker();
10334
- const tresponder = attachSyncSabResponder(tw, tsab, token, { dispatch: dispatch2 });
10365
+ const tsignals = {
10366
+ header: new Int32Array(tsab, 0, SAB_HEADER_I32),
10367
+ interrupt: new AbortController()
10368
+ };
10369
+ threadSignals.set(thread.tid, tsignals);
10370
+ const tdispatch = (req) => dying.serving(
10371
+ () => isWasmSyscall(req) ? process.syscall(req, threadCancel(tsignals)) : dispatchSyncFs(req)
10372
+ );
10373
+ const tresponder = attachSyncSabResponder(tw, tsab, token, { dispatch: tdispatch });
10335
10374
  const onThreadMessage = (event) => {
10336
10375
  const data = event.data;
10337
10376
  if (data?.type === WASM_THREAD_EXIT) endThread(thread.tid);
@@ -10340,6 +10379,7 @@ function spawnWasmProcess(opts) {
10340
10379
  tw.addEventListener("message", onThreadMessage);
10341
10380
  tw.addEventListener("error", onError);
10342
10381
  threads.set(thread.tid, () => {
10382
+ threadSignals.delete(thread.tid);
10343
10383
  tw.removeEventListener("message", onThreadMessage);
10344
10384
  tw.removeEventListener("error", onError);
10345
10385
  tresponder.dispose();