1tube 0.1.19 → 0.1.20
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/package.json +1 -1
- package/src/backends/workerd/backend.ts +71 -75
package/package.json
CHANGED
|
@@ -1352,89 +1352,85 @@ export function createWorkerdBackend(opts: WorkerdBackendOptions): WorkerdBacken
|
|
|
1352
1352
|
|
|
1353
1353
|
// Preflight: refuse to spawn workerd against ports that are
|
|
1354
1354
|
// already in use. Without this, a leftover workerd from a
|
|
1355
|
-
// previous run
|
|
1356
|
-
// surfaces only as
|
|
1357
|
-
//
|
|
1358
|
-
//
|
|
1359
|
-
//
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
`--kill-stale-workerd is set, attempting cleanup...`,
|
|
1368
|
-
);
|
|
1355
|
+
// previous run can satisfy the readiness probe and silently
|
|
1356
|
+
// steal our traffic; the failure then surfaces only as stale
|
|
1357
|
+
// response bodies. On reload the still-serving current process
|
|
1358
|
+
// occupies the OTHER slot's ports by design, so probing the next
|
|
1359
|
+
// slot is safe and catches orphaned older generations.
|
|
1360
|
+
let conflicts = probeSocketsFree(capnp.routes);
|
|
1361
|
+
if (conflicts.length > 0 && opts.killStaleWorkerd) {
|
|
1362
|
+
console.log(
|
|
1363
|
+
`[1tube] port preflight found ${conflicts.length} conflict(s)` +
|
|
1364
|
+
(args.gen > 0 ? ` for reload gen=${args.gen}` : "") +
|
|
1365
|
+
`; --kill-stale-workerd is set, attempting cleanup...`,
|
|
1366
|
+
);
|
|
1369
1367
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
}
|
|
1390
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
1391
|
-
conflicts = probeSocketsFree(capnp.routes);
|
|
1368
|
+
// First try the precise fix: resolve the conflicted port(s)
|
|
1369
|
+
// to their owning PID(s), and kill only owners named workerd.
|
|
1370
|
+
// That is the behavior we want during firmware flashing:
|
|
1371
|
+
// remove the stale candidate that owns 8800, but never kill
|
|
1372
|
+
// a random non-workerd process that happens to be there.
|
|
1373
|
+
const targeted = await killWorkerdOwnersOfPorts(conflicts);
|
|
1374
|
+
if (targeted.attempted) {
|
|
1375
|
+
if (targeted.code === 0) {
|
|
1376
|
+
const details = targeted.stdout?.trim();
|
|
1377
|
+
console.log(
|
|
1378
|
+
`[1tube] targeted stale-workerd cleanup by port complete` +
|
|
1379
|
+
(details ? ` (${details})` : "") +
|
|
1380
|
+
`; re-probing...`,
|
|
1381
|
+
);
|
|
1382
|
+
} else {
|
|
1383
|
+
console.warn(
|
|
1384
|
+
`[1tube] targeted stale-workerd cleanup exited ${targeted.code}` +
|
|
1385
|
+
(targeted.stderr ? `: ${targeted.stderr.trim()}` : ""),
|
|
1386
|
+
);
|
|
1392
1387
|
}
|
|
1388
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
1389
|
+
conflicts = probeSocketsFree(capnp.routes);
|
|
1390
|
+
}
|
|
1393
1391
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
`
|
|
1413
|
-
|
|
1414
|
-
);
|
|
1415
|
-
} else {
|
|
1416
|
-
console.warn(
|
|
1417
|
-
`[1tube] ${result.command?.join(" ")} exited ${result.code}` +
|
|
1418
|
-
(result.stderr ? `: ${result.stderr.trim()}` : ""),
|
|
1419
|
-
);
|
|
1420
|
-
}
|
|
1421
|
-
// Brief settle time: Windows TCP sockets in CLOSE_WAIT can
|
|
1422
|
-
// hold the port for a fraction of a second after the owner
|
|
1423
|
-
// process is killed. 250ms is empirically enough on the
|
|
1424
|
-
// dev boxes we've tested without making the boot path feel
|
|
1425
|
-
// sluggish.
|
|
1426
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
1427
|
-
conflicts = probeSocketsFree(capnp.routes);
|
|
1392
|
+
// If targeted cleanup did not exist on this platform, or it
|
|
1393
|
+
// found no matching workerd owner, fall back to the old typed
|
|
1394
|
+
// process-name cleanup.
|
|
1395
|
+
const result = conflicts.length > 0 ? await killStaleWorkerd() : null;
|
|
1396
|
+
if (result === null) {
|
|
1397
|
+
// Already clear.
|
|
1398
|
+
} else if (result.attempted) {
|
|
1399
|
+
// taskkill returns 128 when no matching image is running —
|
|
1400
|
+
// that's not an error in our context (means the offender
|
|
1401
|
+
// wasn't workerd, which is fine; preflight will catch it).
|
|
1402
|
+
// pkill returns 1 in the same case.
|
|
1403
|
+
const noMatch = (Deno.build.os === "windows" && result.code === 128) ||
|
|
1404
|
+
(Deno.build.os !== "windows" && result.code === 1);
|
|
1405
|
+
if (result.code === 0) {
|
|
1406
|
+
console.log(`[1tube] killed leftover workerd process(es); re-probing...`);
|
|
1407
|
+
} else if (noMatch) {
|
|
1408
|
+
console.log(
|
|
1409
|
+
`[1tube] no leftover workerd processes found; the conflict is held ` +
|
|
1410
|
+
`by something else (re-probing to confirm)...`,
|
|
1411
|
+
);
|
|
1428
1412
|
} else {
|
|
1429
1413
|
console.warn(
|
|
1430
|
-
`[1tube]
|
|
1431
|
-
|
|
1414
|
+
`[1tube] ${result.command?.join(" ")} exited ${result.code}` +
|
|
1415
|
+
(result.stderr ? `: ${result.stderr.trim()}` : ""),
|
|
1432
1416
|
);
|
|
1433
1417
|
}
|
|
1418
|
+
// Brief settle time: Windows TCP sockets in CLOSE_WAIT can
|
|
1419
|
+
// hold the port for a fraction of a second after the owner
|
|
1420
|
+
// process is killed. 250ms is empirically enough on the
|
|
1421
|
+
// dev boxes we've tested without making the boot path feel
|
|
1422
|
+
// sluggish.
|
|
1423
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
1424
|
+
conflicts = probeSocketsFree(capnp.routes);
|
|
1425
|
+
} else {
|
|
1426
|
+
console.warn(
|
|
1427
|
+
`[1tube] could not run ${result.command?.join(" ")}: ` +
|
|
1428
|
+
`${result.stderr ?? "unknown error"}`,
|
|
1429
|
+
);
|
|
1434
1430
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1431
|
+
}
|
|
1432
|
+
if (conflicts.length > 0) {
|
|
1433
|
+
throw new Error(formatPortConflictError(conflicts));
|
|
1438
1434
|
}
|
|
1439
1435
|
|
|
1440
1436
|
const inspectorArgs = buildInspectorExtraArgs(opts.inspectorAddr, slot);
|