@andersbakken/fisk 5.0.2 → 5.0.4
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/daemon/fisk-daemon.js +75 -5
- package/package.json +1 -1
package/daemon/fisk-daemon.js
CHANGED
|
@@ -3433,6 +3433,40 @@ var output = {
|
|
|
3433
3433
|
|
|
3434
3434
|
var fs = libExports;
|
|
3435
3435
|
|
|
3436
|
+
// systemd socket activation: the first passed fd is at SD_LISTEN_FDS_START (3).
|
|
3437
|
+
// See sd_listen_fds(3). systemd sets LISTEN_PID to the PID it should be
|
|
3438
|
+
// consumed by; a child process must be exec'd (not fork+exec of a wrapper)
|
|
3439
|
+
// so its own pid matches. We fail hard on any mismatch rather than silently
|
|
3440
|
+
// falling back to path binding, because that fallback would unlink the
|
|
3441
|
+
// systemd-owned socket file and re-create a new inode, defeating the whole
|
|
3442
|
+
// point of activation (and breaking every docker container that bind-mounted
|
|
3443
|
+
// the socket file).
|
|
3444
|
+
const SD_LISTEN_FDS_START = 3;
|
|
3445
|
+
function systemdListenFd() {
|
|
3446
|
+
const pidRaw = process.env.LISTEN_PID;
|
|
3447
|
+
const fdsRaw = process.env.LISTEN_FDS;
|
|
3448
|
+
// Consume the activation env so any subprocess we spawn does not inherit
|
|
3449
|
+
// stale LISTEN_PID/LISTEN_FDS. sd_listen_fds_with_names(3) recommends
|
|
3450
|
+
// unsetenv after use.
|
|
3451
|
+
delete process.env.LISTEN_PID;
|
|
3452
|
+
delete process.env.LISTEN_FDS;
|
|
3453
|
+
delete process.env.LISTEN_FDNAMES;
|
|
3454
|
+
if (!pidRaw && !fdsRaw) {
|
|
3455
|
+
return "none";
|
|
3456
|
+
}
|
|
3457
|
+
if (!pidRaw || !fdsRaw) {
|
|
3458
|
+
return "mismatch";
|
|
3459
|
+
}
|
|
3460
|
+
const pid = Number(pidRaw);
|
|
3461
|
+
const count = Number(fdsRaw);
|
|
3462
|
+
if (!Number.isInteger(pid) || !Number.isInteger(count) || count < 1) {
|
|
3463
|
+
return "mismatch";
|
|
3464
|
+
}
|
|
3465
|
+
if (pid !== process.pid) {
|
|
3466
|
+
return "mismatch";
|
|
3467
|
+
}
|
|
3468
|
+
return { fd: SD_LISTEN_FDS_START };
|
|
3469
|
+
}
|
|
3436
3470
|
class Server extends EventEmitter__default["default"] {
|
|
3437
3471
|
constructor(option, common) {
|
|
3438
3472
|
super();
|
|
@@ -3443,6 +3477,7 @@ class Server extends EventEmitter__default["default"] {
|
|
|
3443
3477
|
this.option = option;
|
|
3444
3478
|
this._connections = {};
|
|
3445
3479
|
this._connectionId = 0;
|
|
3480
|
+
this._activated = false;
|
|
3446
3481
|
}
|
|
3447
3482
|
close() {
|
|
3448
3483
|
if (this.debug) {
|
|
@@ -3451,14 +3486,49 @@ class Server extends EventEmitter__default["default"] {
|
|
|
3451
3486
|
if (this.server) {
|
|
3452
3487
|
this.server.close();
|
|
3453
3488
|
}
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3489
|
+
// When socket-activated, systemd owns the socket file. Do not unlink
|
|
3490
|
+
// it -- that would break the bind-mount contract for existing clients.
|
|
3491
|
+
if (!this._activated) {
|
|
3492
|
+
try {
|
|
3493
|
+
fs.unlinkSync(this.file);
|
|
3494
|
+
}
|
|
3495
|
+
catch (err) {
|
|
3496
|
+
/* */
|
|
3497
|
+
}
|
|
3459
3498
|
}
|
|
3460
3499
|
}
|
|
3461
3500
|
listen() {
|
|
3501
|
+
const activation = systemdListenFd();
|
|
3502
|
+
if (activation === "mismatch") {
|
|
3503
|
+
console.error("fisk-daemon: LISTEN_FDS/LISTEN_PID present but do not match our pid. Refusing to fall back to path binding -- exiting so systemd can restart us with correct activation.");
|
|
3504
|
+
process.exit(1);
|
|
3505
|
+
}
|
|
3506
|
+
if (activation !== "none") {
|
|
3507
|
+
const inheritedFd = activation.fd;
|
|
3508
|
+
this._activated = true;
|
|
3509
|
+
if (this.debug) {
|
|
3510
|
+
console.log("Server::listen using systemd-activated fd", inheritedFd);
|
|
3511
|
+
}
|
|
3512
|
+
return new Promise((resolve) => {
|
|
3513
|
+
let connected = false;
|
|
3514
|
+
this.server = net__default["default"].createServer(this._onConnection.bind(this));
|
|
3515
|
+
this.server.listen({ fd: inheritedFd }, () => {
|
|
3516
|
+
connected = true;
|
|
3517
|
+
resolve();
|
|
3518
|
+
});
|
|
3519
|
+
this.server.on("error", (err) => {
|
|
3520
|
+
if (!connected) {
|
|
3521
|
+
console.error("Got server error", err);
|
|
3522
|
+
setTimeout(this.listen.bind(this), 1000);
|
|
3523
|
+
}
|
|
3524
|
+
});
|
|
3525
|
+
this.server.on("close", () => {
|
|
3526
|
+
if (!connected) {
|
|
3527
|
+
setTimeout(this.listen.bind(this), 1000);
|
|
3528
|
+
}
|
|
3529
|
+
});
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3462
3532
|
try {
|
|
3463
3533
|
fs.unlinkSync(this.file); // this should be more
|
|
3464
3534
|
// complicated with attempts to
|