@ai-ecoverse/slicc-kernel 1.17.0 → 1.17.2

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.
@@ -1446,6 +1446,25 @@ function ownReady(Fs, read, write) {
1446
1446
  write: write.filter((fd) => flags(fd) & (POLLOUT2 | POLLERR2 | POLLNVAL))
1447
1447
  };
1448
1448
  }
1449
+ function anySelect(Fs, transport, read, write, timeoutMs) {
1450
+ const kernel = (fd) => Fs.getStream(fd)?.sliccKernelFd;
1451
+ const own = (fd) => kernel(fd) === void 0;
1452
+ if (![...read, ...write].some(own)) return kernelSelect(Fs, transport, read, write, timeoutMs);
1453
+ const deadline = timeoutMs < 0 ? Number.POSITIVE_INFINITY : Date.now() + timeoutMs;
1454
+ const kernelRead = read.filter((fd) => !own(fd));
1455
+ const kernelWrite = write.filter((fd) => !own(fd));
1456
+ for (; ; ) {
1457
+ const local = ownReady(Fs, read.filter(own), write.filter(own));
1458
+ const pending = local.read.length > 0 || local.write.length > 0;
1459
+ const slice = pending ? 0 : Math.min(SELECT_SLICE_MS, Math.max(0, deadline - Date.now()));
1460
+ const got = kernelSelect(Fs, transport, kernelRead, kernelWrite, slice);
1461
+ if (typeof got === "number") return got;
1462
+ const ready = { read: [...local.read, ...got.read], write: [...local.write, ...got.write] };
1463
+ if (ready.read.length > 0 || ready.write.length > 0 || Date.now() >= deadline) {
1464
+ return ready;
1465
+ }
1466
+ }
1467
+ }
1449
1468
  function createProcessKernel(deps) {
1450
1469
  const { transport, Fs } = deps;
1451
1470
  const reaped = /* @__PURE__ */ new Map();
@@ -1487,35 +1506,52 @@ function createProcessKernel(deps) {
1487
1506
  Fs.write(stream, r.bytes, 0, r.bytes.length);
1488
1507
  }
1489
1508
  };
1509
+ const execCaptures = /* @__PURE__ */ new Map();
1510
+ const execWait = (pid) => {
1511
+ const r = transport.call({ op: "proc-exec", pid }, Infinity, `exec ${pid}`);
1512
+ if (!r.ok) return -wasiErrno(r.errno);
1513
+ deps.afterChild();
1514
+ return r.kind === "json" ? r.json[1] : 0;
1515
+ };
1516
+ const spawnChild = (file, argv, env, cwd, fds, actions, exec) => {
1517
+ const unflushed = flushed(deps.beforeSpawn);
1518
+ if (unflushed < 0) return unflushed;
1519
+ const promote = deps.stdioPromoter?.();
1520
+ const stdio = [0, 1, 2].map((n) => slot(fds[n] ?? -1, n, promote));
1521
+ const inherit = deps.inherit?.(actions) ?? [];
1522
+ const r = transport.call(
1523
+ {
1524
+ op: "proc-spawn",
1525
+ file,
1526
+ argv,
1527
+ env: env ?? deps.env,
1528
+ cwd: cwd ?? Fs.cwd(),
1529
+ stdio,
1530
+ ...inherit.length > 0 ? { inherit } : {},
1531
+ ...exec ? { exec } : {}
1532
+ },
1533
+ Infinity,
1534
+ `proc-spawn ${file}`
1535
+ );
1536
+ if (!r.ok) return -wasiErrno(r.errno);
1537
+ const pid = r.kind === "json" ? r.json : 0;
1538
+ const captures = [1, 2].filter((n) => "capture" in stdio[n]);
1539
+ if (captures.length === 0) return pid;
1540
+ if (exec) {
1541
+ execCaptures.set(pid, () => {
1542
+ for (const n of captures) deliver(pid, n, fds[n]);
1543
+ });
1544
+ return pid;
1545
+ }
1546
+ const waited = kernelWait(pid, false);
1547
+ if (typeof waited === "number") return waited;
1548
+ for (const n of captures) deliver(pid, n, fds[n]);
1549
+ reaped.set(pid, waited[1]);
1550
+ return pid;
1551
+ };
1490
1552
  return {
1491
1553
  spawn(file, argv, env, cwd, fds, actions) {
1492
- const unflushed = flushed(deps.beforeSpawn);
1493
- if (unflushed < 0) return unflushed;
1494
- const promote = deps.stdioPromoter?.();
1495
- const stdio = [0, 1, 2].map((n) => slot(fds[n] ?? -1, n, promote));
1496
- const inherit = deps.inherit?.(actions) ?? [];
1497
- const r = transport.call(
1498
- {
1499
- op: "proc-spawn",
1500
- file,
1501
- argv,
1502
- env: env ?? deps.env,
1503
- cwd: cwd ?? Fs.cwd(),
1504
- stdio,
1505
- ...inherit.length > 0 ? { inherit } : {}
1506
- },
1507
- Infinity,
1508
- `proc-spawn ${file}`
1509
- );
1510
- if (!r.ok) return -wasiErrno(r.errno);
1511
- const pid = r.kind === "json" ? r.json : 0;
1512
- const captures = [1, 2].filter((n) => "capture" in stdio[n]);
1513
- if (captures.length === 0) return pid;
1514
- const waited = kernelWait(pid, false);
1515
- if (typeof waited === "number") return waited;
1516
- for (const n of captures) deliver(pid, n, fds[n]);
1517
- reaped.set(pid, waited[1]);
1518
- return pid;
1554
+ return spawnChild(file, argv, env, cwd, fds, actions, false);
1519
1555
  },
1520
1556
  fork(state) {
1521
1557
  const unflushed = flushed(deps.beforeSpawn);
@@ -1529,31 +1565,15 @@ function createProcessKernel(deps) {
1529
1565
  if (!r.ok) return -wasiErrno(r.errno);
1530
1566
  return r.kind === "json" ? r.json : -wasiErrno("EIO");
1531
1567
  },
1532
- select(read, write, timeoutMs) {
1533
- const kernel = (fd) => Fs.getStream(fd)?.sliccKernelFd;
1534
- const own = (fd) => kernel(fd) === void 0;
1535
- if (![...read, ...write].some(own))
1536
- return kernelSelect(Fs, transport, read, write, timeoutMs);
1537
- const deadline = timeoutMs < 0 ? Number.POSITIVE_INFINITY : Date.now() + timeoutMs;
1538
- const kernelRead = read.filter((fd) => !own(fd));
1539
- const kernelWrite = write.filter((fd) => !own(fd));
1540
- for (; ; ) {
1541
- const local = ownReady(Fs, read.filter(own), write.filter(own));
1542
- const pending = local.read.length > 0 || local.write.length > 0;
1543
- const slice = pending ? 0 : Math.min(SELECT_SLICE_MS, Math.max(0, deadline - Date.now()));
1544
- const got = kernelSelect(Fs, transport, kernelRead, kernelWrite, slice);
1545
- if (typeof got === "number") return got;
1546
- const ready = { read: [...local.read, ...got.read], write: [...local.write, ...got.write] };
1547
- if (ready.read.length > 0 || ready.write.length > 0 || Date.now() >= deadline) {
1548
- return ready;
1549
- }
1550
- }
1551
- },
1552
- execWait(pid) {
1553
- const r = transport.call({ op: "proc-exec", pid }, Infinity, `exec ${pid}`);
1554
- if (!r.ok) return -wasiErrno(r.errno);
1555
- deps.afterChild();
1556
- return r.kind === "json" ? r.json[1] : 0;
1568
+ select: (read, write, timeoutMs) => anySelect(Fs, transport, read, write, timeoutMs),
1569
+ execWait,
1570
+ execve(file, argv, env, cwd) {
1571
+ const pid = spawnChild(file, argv, env, cwd, [0, 1, 2], void 0, true);
1572
+ if (pid < 0) return pid;
1573
+ const status2 = execWait(pid);
1574
+ execCaptures.get(pid)?.();
1575
+ execCaptures.delete(pid);
1576
+ return status2;
1557
1577
  },
1558
1578
  pause() {
1559
1579
  return status(call2({ op: "sig-pause" }, "pause"));
@@ -3338,20 +3358,20 @@ function pathInode(path) {
3338
3358
  }
3339
3359
  return h;
3340
3360
  }
3341
- function cachingBridge(bridge) {
3361
+ function cachingBridge(bridge, now = () => performance.now()) {
3342
3362
  const stats = /* @__PURE__ */ new Map();
3343
3363
  const lstats = /* @__PURE__ */ new Map();
3344
3364
  const cached = (map, path, get) => {
3345
3365
  let hit = map.get(path);
3346
- if (hit === void 0) {
3366
+ if (hit === void 0 || "until" in hit && hit.until <= now()) {
3347
3367
  try {
3348
3368
  hit = get();
3349
3369
  } catch (e) {
3350
- hit = e;
3370
+ hit = { error: e, until: now() + MISS_TTL_MS };
3351
3371
  }
3352
3372
  map.set(path, hit);
3353
3373
  }
3354
- if (hit instanceof Error) throw hit;
3374
+ if ("until" in hit) throw hit.error;
3355
3375
  return hit;
3356
3376
  };
3357
3377
  const invalidate = () => {
@@ -3401,7 +3421,7 @@ function cachingBridge(bridge) {
3401
3421
  invalidate
3402
3422
  };
3403
3423
  }
3404
- var WasiError, FileBuffer, LocalFile;
3424
+ var WasiError, FileBuffer, LocalFile, MISS_TTL_MS;
3405
3425
  var init_wasi_files = __esm({
3406
3426
  "src/process/wasi/wasi-files.ts"() {
3407
3427
  "use strict";
@@ -3530,6 +3550,7 @@ var init_wasi_files = __esm({
3530
3550
  this.buffer.flush();
3531
3551
  }
3532
3552
  };
3553
+ MISS_TTL_MS = 20;
3533
3554
  }
3534
3555
  });
3535
3556
 
@@ -4292,27 +4313,30 @@ function pollOneoff(deps, inPtr, outPtr, nsubs, neventsPtr) {
4292
4313
  const subs = readSubscriptions(mem, inPtr, nsubs, deps.now);
4293
4314
  const { events, read, write } = classify(deps.fds, subs);
4294
4315
  let interrupted = false;
4316
+ const earliest = subs.reduce((min, s) => Math.min(min, s.deadline), Infinity);
4317
+ const expired = () => performance.now() + CLOCK_SLACK_MS >= earliest;
4295
4318
  if (read.length > 0 || write.length > 0 || events.length === 0) {
4296
- const earliest = Math.min(...subs.map((s) => s.deadline));
4297
- let timeoutMs = -1;
4298
- if (events.length > 0) timeoutMs = 0;
4299
- else if (earliest !== Infinity)
4300
- timeoutMs = Math.max(0, Math.ceil(earliest - performance.now()));
4301
- let ready;
4302
- try {
4303
- ready = kernel.call({ op: "fd-select", read, write, timeoutMs });
4304
- } catch (e) {
4305
- if (!deps.interruptWakes || e.code !== "EINTR") throw e;
4306
- interrupted = true;
4307
- ready = { read: [], write: [] };
4308
- }
4309
- events.push(
4310
- ...readyEvents(subs, ready)
4311
- );
4319
+ do {
4320
+ let timeoutMs = -1;
4321
+ if (events.length > 0) timeoutMs = 0;
4322
+ else if (earliest !== Infinity)
4323
+ timeoutMs = Math.max(0, Math.ceil(earliest - performance.now()));
4324
+ let ready;
4325
+ try {
4326
+ ready = kernel.call({ op: "fd-select", read, write, timeoutMs });
4327
+ } catch (e) {
4328
+ if (!deps.interruptWakes || e.code !== "EINTR") throw e;
4329
+ interrupted = true;
4330
+ ready = { read: [], write: [] };
4331
+ }
4332
+ events.push(
4333
+ ...readyEvents(subs, ready)
4334
+ );
4335
+ } while (events.length === 0 && !interrupted && earliest !== Infinity && !expired());
4312
4336
  }
4313
4337
  const after = performance.now();
4314
4338
  for (const s of subs) {
4315
- if (s.type === EVENTTYPE.CLOCK && (interrupted || s.deadline <= after + 0.5)) {
4339
+ if (s.type === EVENTTYPE.CLOCK && (interrupted || s.deadline <= after + CLOCK_SLACK_MS)) {
4316
4340
  events.push({ userdata: s.userdata, error: E.SUCCESS, type: s.type });
4317
4341
  }
4318
4342
  }
@@ -4320,10 +4344,12 @@ function pollOneoff(deps, inPtr, outPtr, nsubs, neventsPtr) {
4320
4344
  mem.view().setUint32(neventsPtr, events.length, true);
4321
4345
  return E.SUCCESS;
4322
4346
  }
4347
+ var CLOCK_SLACK_MS;
4323
4348
  var init_wasi_poll = __esm({
4324
4349
  "src/process/wasi/wasi-poll.ts"() {
4325
4350
  "use strict";
4326
4351
  init_wasi_abi();
4352
+ CLOCK_SLACK_MS = 0.5;
4327
4353
  }
4328
4354
  });
4329
4355
 
@@ -4451,19 +4477,25 @@ var init_wasi_host = __esm({
4451
4477
  ...this.statImports(),
4452
4478
  ...this.pathImports(),
4453
4479
  ...this.socketImports(),
4454
- poll_oneoff: (inPtr, outPtr, n, nevents) => pollOneoff(
4455
- {
4456
- mem: this.mem,
4457
- fds: this.fds,
4458
- kernel: this.o.kernel,
4459
- now: (id) => this.now(id),
4460
- interruptWakes: this.interruptWakes
4461
- },
4462
- inPtr,
4463
- outPtr,
4464
- n,
4465
- nevents
4466
- )
4480
+ poll_oneoff: (inPtr, outPtr, n, nevents) => {
4481
+ try {
4482
+ return pollOneoff(
4483
+ {
4484
+ mem: this.mem,
4485
+ fds: this.fds,
4486
+ kernel: this.o.kernel,
4487
+ now: (id) => this.now(id),
4488
+ interruptWakes: this.interruptWakes
4489
+ },
4490
+ inPtr,
4491
+ outPtr,
4492
+ n,
4493
+ nevents
4494
+ );
4495
+ } finally {
4496
+ this.o.fs.invalidate?.();
4497
+ }
4498
+ }
4467
4499
  });
4468
4500
  return this.cache;
4469
4501
  }
@@ -5818,7 +5850,7 @@ var init_wasix_process = __esm({
5818
5850
  ...op.oflags & OFLAG_TRUNC ? { truncate: true } : {}
5819
5851
  });
5820
5852
  }
5821
- spawn(req) {
5853
+ spawn(req, exec = false) {
5822
5854
  const { stdio, inherit, cwd, opened } = this.childFds(req.ops ?? []);
5823
5855
  try {
5824
5856
  return this.call({
@@ -5828,7 +5860,8 @@ var init_wasix_process = __esm({
5828
5860
  env: req.env ?? this.environment(),
5829
5861
  cwd,
5830
5862
  stdio,
5831
- inherit
5863
+ inherit,
5864
+ ...exec ? { exec } : {}
5832
5865
  });
5833
5866
  } finally {
5834
5867
  for (const kfd of opened) this.host.o.kernel.sys.close(kfd);
@@ -5836,7 +5869,7 @@ var init_wasix_process = __esm({
5836
5869
  }
5837
5870
  }
5838
5871
  exec(req) {
5839
- const pid = this.spawn(req);
5872
+ const pid = this.spawn(req, true);
5840
5873
  const [, status2] = this.call({ op: "proc-exec", pid });
5841
5874
  const sig = status2 & 127;
5842
5875
  throw new WasiExit(sig ? 128 + sig : status2 >> 8 & 255);