@push.rocks/smartdaemon 2.21.0 → 2.22.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.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.systemdtransientscope.js +1 -1
- package/dist_ts/classes.systemdunit.js +1 -1
- package/dist_ts/classes.systemdunitfile.js +1 -1
- package/dist_ts/smartdaemon.classes.systemdmanager.js +1 -1
- package/dist_ts/smartdaemon.paths.js +1 -1
- package/dist_ts/systemd.definition.d.ts +3 -3
- package/dist_ts/systemd.userenvironment.d.ts +1 -1
- package/dist_ts_systemdruntime/classes.systemdnotifier.d.ts +82 -0
- package/dist_ts_systemdruntime/classes.systemdnotifier.js +217 -0
- package/dist_ts_systemdruntime/classes.systemdruntimeerror.d.ts +31 -0
- package/dist_ts_systemdruntime/classes.systemdruntimeerror.js +9 -0
- package/dist_ts_systemdruntime/index.d.ts +5 -0
- package/dist_ts_systemdruntime/index.js +14 -0
- package/dist_ts_systemdruntime/systemdruntime.libc.d.ts +87 -0
- package/dist_ts_systemdruntime/systemdruntime.libc.js +92 -0
- package/dist_ts_systemdruntime/systemdruntime.listen.d.ts +46 -0
- package/dist_ts_systemdruntime/systemdruntime.listen.js +136 -0
- package/dist_ts_systemdruntime/systemdruntime.validation.d.ts +13 -0
- package/dist_ts_systemdruntime/systemdruntime.validation.js +29 -0
- package/package.json +18 -6
- package/readme.md +102 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_systemdruntime/classes.systemdnotifier.ts +287 -0
- package/ts_systemdruntime/classes.systemdruntimeerror.ts +53 -0
- package/ts_systemdruntime/index.ts +22 -0
- package/ts_systemdruntime/systemdruntime.libc.ts +121 -0
- package/ts_systemdruntime/systemdruntime.listen.ts +153 -0
- package/ts_systemdruntime/systemdruntime.validation.ts +41 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { SystemdRuntimeError } from './classes.systemdruntimeerror.js';
|
|
2
|
+
import { controlSpace, descriptorsPerMessageMaximum, libcConstants, socketAddressLength, systemdLibc, writeSocketAddress, } from './systemdruntime.libc.js';
|
|
3
|
+
import { assertSystemdDescriptor, assertSystemdNotifySocketAddress, isSystemdDescriptorName, } from './systemdruntime.validation.js';
|
|
4
|
+
/** `NOTIFY_BUFFER_MAX` (`PIPE_BUF`): systemd ignores a longer notification message. */
|
|
5
|
+
export const notifyMessageMaximumBytes = 4096;
|
|
6
|
+
/**
|
|
7
|
+
* Takes `NOTIFY_SOCKET` out of the environment: the validated address, or null when it is unset or
|
|
8
|
+
* empty. An address that is set but invalid is removed as well and then refused
|
|
9
|
+
* (`notify_socket_invalid`).
|
|
10
|
+
*/
|
|
11
|
+
export const takeSystemdNotifySocket = (optionsArg = {}) => {
|
|
12
|
+
const env = optionsArg.env ?? process.env;
|
|
13
|
+
const address = env.NOTIFY_SOCKET;
|
|
14
|
+
delete env.NOTIFY_SOCKET;
|
|
15
|
+
if (address === undefined || address === '')
|
|
16
|
+
return null;
|
|
17
|
+
assertSystemdNotifySocketAddress(address);
|
|
18
|
+
return address;
|
|
19
|
+
};
|
|
20
|
+
const fieldNamePattern = /^[A-Z][A-Z0-9_]*$/;
|
|
21
|
+
/**
|
|
22
|
+
* Sends `sd_notify(3)` messages to a service manager's notification socket: one `AF_UNIX`
|
|
23
|
+
* `SOCK_DGRAM` datagram per message, descriptors attached as `SCM_RIGHTS`. Every call is synchronous
|
|
24
|
+
* and either delivers the whole message to the socket or throws a `SystemdRuntimeError`; whether
|
|
25
|
+
* the manager acts on it depends on the unit's `NotifyAccess=`. Fields and descriptor names are
|
|
26
|
+
* validated before sending, because systemd ignores a message it cannot parse without telling the
|
|
27
|
+
* sender.
|
|
28
|
+
*/
|
|
29
|
+
export class SystemdNotifier {
|
|
30
|
+
/**
|
|
31
|
+
* The notifier for the unit that started this process, or null when `NOTIFY_SOCKET` is unset or
|
|
32
|
+
* empty — the process was not started by a service manager that listens. The caller decides what
|
|
33
|
+
* that means; nothing is sent silently nowhere. An invalid `NOTIFY_SOCKET` throws
|
|
34
|
+
* `notify_socket_invalid`.
|
|
35
|
+
*/
|
|
36
|
+
static fromEnvironment(optionsArg = {}) {
|
|
37
|
+
const env = optionsArg.env ?? process.env;
|
|
38
|
+
const address = optionsArg.take === true ? takeSystemdNotifySocket({ env }) : env.NOTIFY_SOCKET;
|
|
39
|
+
if (address === undefined || address === null || address === '')
|
|
40
|
+
return null;
|
|
41
|
+
return new SystemdNotifier(address);
|
|
42
|
+
}
|
|
43
|
+
constructor(socketAddressArg) {
|
|
44
|
+
assertSystemdNotifySocketAddress(socketAddressArg);
|
|
45
|
+
this.socketAddress = socketAddressArg;
|
|
46
|
+
}
|
|
47
|
+
/** `READY=1`, with an optional `STATUS=`. */
|
|
48
|
+
ready(statusArg) {
|
|
49
|
+
this.send({ READY: '1', ...(statusArg === undefined ? {} : { STATUS: statusArg }) });
|
|
50
|
+
}
|
|
51
|
+
/** `STATUS=`: free-form text the manager shows as the unit's status. */
|
|
52
|
+
status(textArg) {
|
|
53
|
+
this.send({ STATUS: textArg });
|
|
54
|
+
}
|
|
55
|
+
/** `STOPPING=1`, with an optional `STATUS=`. */
|
|
56
|
+
stopping(statusArg) {
|
|
57
|
+
this.send({ STOPPING: '1', ...(statusArg === undefined ? {} : { STATUS: statusArg }) });
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `RELOADING=1` with `MONOTONIC_USEC=` (`CLOCK_MONOTONIC` now), with an optional `STATUS=`. The
|
|
61
|
+
* service sends `ready()` once the reload finished.
|
|
62
|
+
*/
|
|
63
|
+
reloading(statusArg) {
|
|
64
|
+
this.send({
|
|
65
|
+
RELOADING: '1',
|
|
66
|
+
MONOTONIC_USEC: String(monotonicMicroseconds()),
|
|
67
|
+
...(statusArg === undefined ? {} : { STATUS: statusArg }),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** `WATCHDOG=1`: keeps a `WatchdogSec=` unit alive. */
|
|
71
|
+
watchdog() {
|
|
72
|
+
this.send({ WATCHDOG: '1' });
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* `EXTEND_TIMEOUT_USEC=`: asks the manager to wait `microsecondsArg` longer for the current start,
|
|
76
|
+
* runtime-start, stop or watchdog deadline, with an optional `STATUS=`.
|
|
77
|
+
*/
|
|
78
|
+
extendTimeout(microsecondsArg, statusArg) {
|
|
79
|
+
if (!Number.isSafeInteger(microsecondsArg) || microsecondsArg <= 0) {
|
|
80
|
+
throw new SystemdRuntimeError('notify_field_invalid', 'EXTEND_TIMEOUT_USEC must be a positive integer.');
|
|
81
|
+
}
|
|
82
|
+
this.send({
|
|
83
|
+
EXTEND_TIMEOUT_USEC: String(microsecondsArg),
|
|
84
|
+
...(statusArg === undefined ? {} : { STATUS: statusArg }),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* `FDSTORE=1` with `FDNAME=`: the manager keeps duplicates of `descriptorsArg` (1–253) under
|
|
89
|
+
* `nameArg` in the unit's descriptor store (`FileDescriptorStoreMax=`) and passes them to the
|
|
90
|
+
* next main process through `LISTEN_FDS`. Storing does not replace descriptors already stored
|
|
91
|
+
* under the name; `replaceDescriptors()` does.
|
|
92
|
+
*/
|
|
93
|
+
storeDescriptors(nameArg, descriptorsArg, optionsArg = {}) {
|
|
94
|
+
assertDescriptorName(nameArg);
|
|
95
|
+
assertStoredDescriptors(descriptorsArg);
|
|
96
|
+
this.send({ FDSTORE: '1', FDNAME: nameArg, ...(optionsArg.poll === false ? { FDPOLL: '0' } : {}) }, descriptorsArg);
|
|
97
|
+
}
|
|
98
|
+
/** `FDSTOREREMOVE=1` with `FDNAME=`: the manager closes every descriptor stored under `nameArg`. */
|
|
99
|
+
removeDescriptors(nameArg) {
|
|
100
|
+
assertDescriptorName(nameArg);
|
|
101
|
+
this.send({ FDSTOREREMOVE: '1', FDNAME: nameArg });
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Removes the descriptors stored under `nameArg`, then stores `descriptorsArg` under it: two
|
|
105
|
+
* messages, handled by the manager in order. Between them the store holds nothing under the name.
|
|
106
|
+
*/
|
|
107
|
+
replaceDescriptors(nameArg, descriptorsArg, optionsArg = {}) {
|
|
108
|
+
assertDescriptorName(nameArg);
|
|
109
|
+
assertStoredDescriptors(descriptorsArg);
|
|
110
|
+
this.removeDescriptors(nameArg);
|
|
111
|
+
this.storeDescriptors(nameArg, descriptorsArg, optionsArg);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Sends one message: `NAME=value` fields in insertion order, joined by newlines, and up to 253
|
|
115
|
+
* descriptors. Names are upper-case (`A–Z`, digits, `_`); values carry no newline or NUL; the
|
|
116
|
+
* message is at most 4096 bytes.
|
|
117
|
+
*/
|
|
118
|
+
send(fieldsArg, descriptorsArg = []) {
|
|
119
|
+
const entries = Object.entries(fieldsArg);
|
|
120
|
+
if (entries.length === 0) {
|
|
121
|
+
throw new SystemdRuntimeError('notify_field_invalid', 'A notification needs at least one field.');
|
|
122
|
+
}
|
|
123
|
+
for (const [name, value] of entries) {
|
|
124
|
+
if (!fieldNamePattern.test(name)) {
|
|
125
|
+
throw new SystemdRuntimeError('notify_field_invalid', `${JSON.stringify(name)} is not a notification field name.`);
|
|
126
|
+
}
|
|
127
|
+
if (typeof value !== 'string' || /[\n\0]/.test(value)) {
|
|
128
|
+
throw new SystemdRuntimeError('notify_field_invalid', `The ${name} value must be a string without newline or NUL.`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
assertDescriptorList(descriptorsArg);
|
|
132
|
+
const payload = Buffer.from(entries.map(([name, value]) => `${name}=${value}`).join('\n'), 'utf8');
|
|
133
|
+
if (payload.length > notifyMessageMaximumBytes) {
|
|
134
|
+
throw new SystemdRuntimeError('notify_field_invalid', `The message is ${payload.length} bytes; systemd reads at most ${notifyMessageMaximumBytes}.`);
|
|
135
|
+
}
|
|
136
|
+
sendDatagram(this.socketAddress, payload, descriptorsArg);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const assertDescriptorName = (nameArg) => {
|
|
140
|
+
if (!isSystemdDescriptorName(nameArg, true)) {
|
|
141
|
+
throw new SystemdRuntimeError('descriptor_name_invalid', 'A descriptor name is 1–255 printable ASCII characters without ":".');
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
/** At most 253 valid descriptor numbers. */
|
|
145
|
+
const assertDescriptorList = (descriptorsArg) => {
|
|
146
|
+
if (descriptorsArg.length > descriptorsPerMessageMaximum) {
|
|
147
|
+
throw new SystemdRuntimeError('descriptor_invalid', `One message carries at most ${descriptorsPerMessageMaximum} descriptors.`);
|
|
148
|
+
}
|
|
149
|
+
descriptorsArg.forEach(assertSystemdDescriptor);
|
|
150
|
+
};
|
|
151
|
+
/** 1–253 valid descriptor numbers, as `FDSTORE=1` needs. */
|
|
152
|
+
const assertStoredDescriptors = (descriptorsArg) => {
|
|
153
|
+
if (descriptorsArg.length === 0) {
|
|
154
|
+
throw new SystemdRuntimeError('descriptor_invalid', 'FDSTORE=1 needs at least one descriptor.');
|
|
155
|
+
}
|
|
156
|
+
assertDescriptorList(descriptorsArg);
|
|
157
|
+
};
|
|
158
|
+
/** `CLOCK_MONOTONIC` in microseconds, as `MONOTONIC_USEC=` expects. */
|
|
159
|
+
const monotonicMicroseconds = () => {
|
|
160
|
+
const libc = systemdLibc();
|
|
161
|
+
const timespec = Buffer.alloc(16);
|
|
162
|
+
if (libc.functions.clock_gettime(libcConstants.CLOCK_MONOTONIC, timespec) !== 0) {
|
|
163
|
+
throw new SystemdRuntimeError('notify_failed', 'clock_gettime(CLOCK_MONOTONIC) failed.', { errno: libc.errno() });
|
|
164
|
+
}
|
|
165
|
+
return timespec.readBigInt64LE(0) * 1000000n + timespec.readBigInt64LE(8) / 1000n;
|
|
166
|
+
};
|
|
167
|
+
// One block holds the whole message, so every pointer inside it stays valid while the block is
|
|
168
|
+
// borrowed by the call: msghdr, iovec, sockaddr_un, control data, payload.
|
|
169
|
+
const iovecOffset = 56;
|
|
170
|
+
const addressOffset = 72;
|
|
171
|
+
const controlOffset = 184;
|
|
172
|
+
const sendDatagram = (addressArg, payloadArg, descriptorsArg) => {
|
|
173
|
+
const libc = systemdLibc();
|
|
174
|
+
const space = descriptorsArg.length === 0 ? 0 : controlSpace(descriptorsArg.length);
|
|
175
|
+
const payloadOffset = controlOffset + space;
|
|
176
|
+
const block = Buffer.alloc(payloadOffset + payloadArg.length);
|
|
177
|
+
const base = libc.ffi.getRawPointer(block);
|
|
178
|
+
writeSocketAddress(block, addressOffset, addressArg);
|
|
179
|
+
payloadArg.copy(block, payloadOffset);
|
|
180
|
+
block.writeBigUInt64LE(base + BigInt(addressOffset), 0);
|
|
181
|
+
block.writeUInt32LE(socketAddressLength(addressArg), 8);
|
|
182
|
+
block.writeBigUInt64LE(base + BigInt(iovecOffset), 16);
|
|
183
|
+
block.writeBigUInt64LE(1n, 24);
|
|
184
|
+
block.writeBigUInt64LE(base + BigInt(payloadOffset), iovecOffset);
|
|
185
|
+
block.writeBigUInt64LE(BigInt(payloadArg.length), iovecOffset + 8);
|
|
186
|
+
if (space > 0) {
|
|
187
|
+
block.writeBigUInt64LE(base + BigInt(controlOffset), 32);
|
|
188
|
+
block.writeBigUInt64LE(BigInt(space), 40);
|
|
189
|
+
block.writeBigUInt64LE(BigInt(16 + 4 * descriptorsArg.length), controlOffset);
|
|
190
|
+
block.writeInt32LE(libcConstants.SOL_SOCKET, controlOffset + 8);
|
|
191
|
+
block.writeInt32LE(libcConstants.SCM_RIGHTS, controlOffset + 12);
|
|
192
|
+
descriptorsArg.forEach((descriptor, index) => block.writeInt32LE(descriptor, controlOffset + 16 + 4 * index));
|
|
193
|
+
}
|
|
194
|
+
const socket = libc.functions.socket(libcConstants.AF_UNIX, libcConstants.SOCK_DGRAM | libcConstants.SOCK_CLOEXEC, 0);
|
|
195
|
+
if (socket < 0) {
|
|
196
|
+
throw new SystemdRuntimeError('notify_failed', 'socket(AF_UNIX, SOCK_DGRAM) failed.', { errno: libc.errno() });
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
let sent = libc.functions.sendmsg(socket, block, libcConstants.MSG_NOSIGNAL);
|
|
200
|
+
let errno = sent < 0n ? libc.errno() : 0;
|
|
201
|
+
while (sent < 0n && errno === libcConstants.EINTR) {
|
|
202
|
+
sent = libc.functions.sendmsg(socket, block, libcConstants.MSG_NOSIGNAL);
|
|
203
|
+
errno = sent < 0n ? libc.errno() : 0;
|
|
204
|
+
}
|
|
205
|
+
if (sent < 0n) {
|
|
206
|
+
throw new SystemdRuntimeError('notify_failed', `sendmsg to ${addressArg} failed.`, { errno });
|
|
207
|
+
}
|
|
208
|
+
if (sent !== BigInt(payloadArg.length)) {
|
|
209
|
+
throw new SystemdRuntimeError('notify_failed', `sendmsg to ${addressArg} sent ${sent} of ${payloadArg.length} bytes.`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
// Linux releases the descriptor whatever close(2) reports; the socket is this call's alone.
|
|
214
|
+
libc.functions.close(socket);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zeXN0ZW1kbm90aWZpZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zeXN0ZW1kcnVudGltZS9jbGFzc2VzLnN5c3RlbWRub3RpZmllci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUN2RSxPQUFPLEVBQ0wsWUFBWSxFQUNaLDRCQUE0QixFQUM1QixhQUFhLEVBQ2IsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxrQkFBa0IsR0FDbkIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGdDQUFnQyxFQUNoQyx1QkFBdUIsR0FDeEIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUV4Qyx1RkFBdUY7QUFDdkYsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsSUFBSSxDQUFDO0FBcUI5Qzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxVQUFVLEdBQStCLEVBQUUsRUFBaUIsRUFBRTtJQUNwRyxNQUFNLEdBQUcsR0FBRyxVQUFVLENBQUMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUM7SUFDMUMsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQztJQUNsQyxPQUFPLEdBQUcsQ0FBQyxhQUFhLENBQUM7SUFDekIsSUFBSSxPQUFPLEtBQUssU0FBUyxJQUFJLE9BQU8sS0FBSyxFQUFFO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDekQsZ0NBQWdDLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUMsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxnQkFBZ0IsR0FBRyxtQkFBbUIsQ0FBQztBQUU3Qzs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFDMUI7Ozs7O09BS0c7SUFDSSxNQUFNLENBQUMsZUFBZSxDQUFDLFVBQVUsR0FBdUMsRUFBRTtR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
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why a systemd runtime operation refused or failed:
|
|
3
|
+
*
|
|
4
|
+
* - `runtime_unsupported`: the runtime cannot make the call: Node.js older than 26, a platform
|
|
5
|
+
* other than Linux on x64 or arm64, a C library other than glibc (`libc.so.6`), `node:ffi`
|
|
6
|
+
* disabled (`--no-experimental-ffi`) or denied by the permission model (no `--allow-ffi`).
|
|
7
|
+
* - `notify_socket_invalid`: `NOTIFY_SOCKET` is not an `AF_UNIX` path or abstract name this
|
|
8
|
+
* module can address (`vsock:` addresses included).
|
|
9
|
+
* - `notify_field_invalid`: a notification field name or value systemd would not parse, or a
|
|
10
|
+
* message larger than systemd reads (4096 bytes).
|
|
11
|
+
* - `notify_failed`: the message could not be sent (`errno` names why).
|
|
12
|
+
* - `descriptor_name_invalid`: an `FDNAME=` systemd would refuse.
|
|
13
|
+
* - `descriptor_invalid`: a descriptor number that cannot exist, or a count outside 1–253.
|
|
14
|
+
* - `listen_environment_invalid`: `LISTEN_PID`, `LISTEN_FDS` or `LISTEN_FDNAMES` is malformed,
|
|
15
|
+
* `LISTEN_FDS` names a descriptor at or above the process's hard `RLIMIT_NOFILE`, or
|
|
16
|
+
* `getrlimit(RLIMIT_NOFILE)` failed, so the count cannot be bounded (`errno` names why).
|
|
17
|
+
* - `watchdog_environment_invalid`: `WATCHDOG_USEC` or `WATCHDOG_PID` is malformed.
|
|
18
|
+
* - `close_on_exec_failed`: a descriptor could not be marked close-on-exec (`errno` names why).
|
|
19
|
+
*/
|
|
20
|
+
export type TSystemdRuntimeErrorCode = 'runtime_unsupported' | 'notify_socket_invalid' | 'notify_field_invalid' | 'notify_failed' | 'descriptor_name_invalid' | 'descriptor_invalid' | 'listen_environment_invalid' | 'watchdog_environment_invalid' | 'close_on_exec_failed';
|
|
21
|
+
export interface ISystemdRuntimeErrorOptions {
|
|
22
|
+
/** The C library's `errno` after the failed call, when a call failed. */
|
|
23
|
+
readonly errno?: number;
|
|
24
|
+
readonly cause?: unknown;
|
|
25
|
+
}
|
|
26
|
+
export declare class SystemdRuntimeError extends Error {
|
|
27
|
+
readonly code: TSystemdRuntimeErrorCode;
|
|
28
|
+
/** The C library's `errno` after the failed call, or null when no call failed. */
|
|
29
|
+
readonly errno: number | null;
|
|
30
|
+
constructor(code: TSystemdRuntimeErrorCode, messageArg: string, optionsArg?: ISystemdRuntimeErrorOptions);
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export class SystemdRuntimeError extends Error {
|
|
2
|
+
constructor(code, messageArg, optionsArg = {}) {
|
|
3
|
+
super(`${messageArg}${optionsArg.errno === undefined ? '' : ` (errno ${optionsArg.errno})`}`, optionsArg.cause === undefined ? undefined : { cause: optionsArg.cause });
|
|
4
|
+
this.code = code;
|
|
5
|
+
this.name = 'SystemdRuntimeError';
|
|
6
|
+
this.errno = optionsArg.errno ?? null;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zeXN0ZW1kcnVudGltZWVycm9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfc3lzdGVtZHJ1bnRpbWUvY2xhc3Nlcy5zeXN0ZW1kcnVudGltZWVycm9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQW9DQSxNQUFNLE9BQU8sbUJBQW9CLFNBQVEsS0FBSztJQUk1QyxZQUNrQixJQUE4QixFQUM5QyxVQUFrQixFQUNsQixVQUFVLEdBQWdDLEVBQUU7UUFFNUMsS0FBSyxDQUNILEdBQUcsVUFBVSxHQUFHLFVBQVUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsVUFBVSxDQUFDLEtBQUssR0FBRyxFQUFFLEVBQ3RGLFVBQVUsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FDekUsQ0FBQztvQkFQYyxJQUFJO1FBUXBCLElBQUksQ0FBQyxJQUFJLEdBQUcscUJBQXFCLENBQUM7UUFDbEMsSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQztJQUN4QyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * from './classes.systemdruntimeerror.js';
|
|
2
|
+
export * from './classes.systemdnotifier.js';
|
|
3
|
+
export { type ISystemdListenDescriptor, type ISystemdProcessEnvironmentOptions, setCloseOnExec, systemdListenDescriptorsStart, takeSystemdListenDescriptors, watchdogIntervalUsec, } from './systemdruntime.listen.js';
|
|
4
|
+
export { systemdRuntimeNodeMajor } from './systemdruntime.libc.js';
|
|
5
|
+
export { isSystemdDescriptorName, isSystemdNotifySocketAddress } from './systemdruntime.validation.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@push.rocks/smartdaemon/systemd-runtime`: the service side of systemd for a Node.js main
|
|
3
|
+
* process — `sd_notify(3)` messages with descriptors, `LISTEN_FDS` adoption with close-on-exec, and
|
|
4
|
+
* the watchdog interval — through glibc calls made with `node:ffi`. Requires Node.js 26 or later:
|
|
5
|
+
* importing it on an older Node.js throws `SystemdRuntimeError` `runtime_unsupported`.
|
|
6
|
+
*/
|
|
7
|
+
import { assertSystemdRuntimeNode } from './systemdruntime.libc.js';
|
|
8
|
+
export * from './classes.systemdruntimeerror.js';
|
|
9
|
+
export * from './classes.systemdnotifier.js';
|
|
10
|
+
export { setCloseOnExec, systemdListenDescriptorsStart, takeSystemdListenDescriptors, watchdogIntervalUsec, } from './systemdruntime.listen.js';
|
|
11
|
+
export { systemdRuntimeNodeMajor } from './systemdruntime.libc.js';
|
|
12
|
+
export { isSystemdDescriptorName, isSystemdNotifySocketAddress } from './systemdruntime.validation.js';
|
|
13
|
+
assertSystemdRuntimeNode();
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zeXN0ZW1kcnVudGltZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUNILE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXBFLGNBQWMsa0NBQWtDLENBQUM7QUFDakQsY0FBYyw4QkFBOEIsQ0FBQztBQUM3QyxPQUFPLEVBR0wsY0FBYyxFQUNkLDZCQUE2QixFQUM3Qiw0QkFBNEIsRUFDNUIsb0JBQW9CLEdBQ3JCLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDbkUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLDRCQUE0QixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFdkcsd0JBQXdCLEVBQUUsQ0FBQyJ9
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type * as ffi from 'node:ffi';
|
|
2
|
+
/** The first Node.js major with `node:ffi`, which this module calls libc through. */
|
|
3
|
+
export declare const systemdRuntimeNodeMajor = 26;
|
|
4
|
+
/** Internal: refuses a Node.js older than `systemdRuntimeNodeMajor`; the subpath runs it on import. */
|
|
5
|
+
export declare const assertSystemdRuntimeNode: (versionArg?: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* The generic Linux values both qualified targets (x86_64 and aarch64, glibc) use. The structure
|
|
8
|
+
* layouts below are the LP64 glibc ones, identical on both:
|
|
9
|
+
*
|
|
10
|
+
* - `sockaddr_un`: `sa_family_t` (u16) at 0, `sun_path[108]` at 2.
|
|
11
|
+
* - `iovec` (16 bytes): `iov_base` at 0, `iov_len` at 8.
|
|
12
|
+
* - `msghdr` (56 bytes): `msg_name` at 0, `msg_namelen` (u32) at 8, `msg_iov` at 16, `msg_iovlen`
|
|
13
|
+
* at 24, `msg_control` at 32, `msg_controllen` at 40, `msg_flags` at 48.
|
|
14
|
+
* - `cmsghdr`: `cmsg_len` (size_t) at 0, `cmsg_level` at 8, `cmsg_type` at 12, data at 16;
|
|
15
|
+
* `CMSG_LEN(n)` is 16 + n and `CMSG_SPACE(n)` 16 + n rounded up to 8.
|
|
16
|
+
* - `timespec` (16 bytes): `tv_sec` at 0, `tv_nsec` at 8.
|
|
17
|
+
* - `rlimit` (16 bytes): `rlim_cur` (u64) at 0, `rlim_max` (u64) at 8; `RLIM_INFINITY` is all ones.
|
|
18
|
+
*/
|
|
19
|
+
export declare const libcConstants: {
|
|
20
|
+
readonly AF_UNIX: 1;
|
|
21
|
+
readonly SOCK_DGRAM: 2;
|
|
22
|
+
readonly SOCK_CLOEXEC: 524288;
|
|
23
|
+
readonly SOL_SOCKET: 1;
|
|
24
|
+
readonly SCM_RIGHTS: 1;
|
|
25
|
+
readonly MSG_NOSIGNAL: 16384;
|
|
26
|
+
readonly F_GETFD: 1;
|
|
27
|
+
readonly F_SETFD: 2;
|
|
28
|
+
readonly FD_CLOEXEC: 1;
|
|
29
|
+
readonly CLOCK_MONOTONIC: 1;
|
|
30
|
+
readonly EINTR: 4;
|
|
31
|
+
readonly RLIMIT_NOFILE: 7;
|
|
32
|
+
};
|
|
33
|
+
/** `sun_path` is 108 bytes; an address of up to 107 bytes keeps a path's terminating NUL. */
|
|
34
|
+
export declare const socketAddressMaximumBytes = 107;
|
|
35
|
+
/** The kernel's `SCM_MAX_FD`: the most descriptors one `SCM_RIGHTS` message carries. */
|
|
36
|
+
export declare const descriptorsPerMessageMaximum = 253;
|
|
37
|
+
declare const libcFunctions: {
|
|
38
|
+
readonly socket: {
|
|
39
|
+
readonly arguments: readonly ["int32", "int32", "int32"];
|
|
40
|
+
readonly return: 'int32';
|
|
41
|
+
};
|
|
42
|
+
readonly sendmsg: {
|
|
43
|
+
readonly arguments: readonly ["int32", "pointer", "int32"];
|
|
44
|
+
readonly return: 'int64';
|
|
45
|
+
};
|
|
46
|
+
readonly close: {
|
|
47
|
+
readonly arguments: readonly ["int32"];
|
|
48
|
+
readonly return: 'int32';
|
|
49
|
+
};
|
|
50
|
+
readonly fcntl: {
|
|
51
|
+
readonly arguments: readonly ["int32", "int32", "int32"];
|
|
52
|
+
readonly return: 'int32';
|
|
53
|
+
};
|
|
54
|
+
readonly clock_gettime: {
|
|
55
|
+
readonly arguments: readonly ["int32", "pointer"];
|
|
56
|
+
readonly return: 'int32';
|
|
57
|
+
};
|
|
58
|
+
readonly getrlimit: {
|
|
59
|
+
readonly arguments: readonly ["int32", "pointer"];
|
|
60
|
+
readonly return: 'int32';
|
|
61
|
+
};
|
|
62
|
+
readonly __errno_location: {
|
|
63
|
+
readonly arguments: readonly [];
|
|
64
|
+
readonly return: 'pointer';
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export interface ISystemdLibc {
|
|
68
|
+
readonly functions: ffi.WrappedFunctionsFromDefinitions<typeof libcFunctions>;
|
|
69
|
+
readonly ffi: typeof ffi;
|
|
70
|
+
/**
|
|
71
|
+
* The calling thread's `errno`, read through glibc's `__errno_location()`. `node:ffi` has no errno
|
|
72
|
+
* API; read it immediately after the failed call, before anything else runs on the thread.
|
|
73
|
+
*/
|
|
74
|
+
errno(): number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* glibc, opened through `node:ffi` on first use and kept for the process lifetime. Loading
|
|
78
|
+
* `node:ffi` emits Node's ExperimentalWarning once.
|
|
79
|
+
*/
|
|
80
|
+
export declare const systemdLibc: () => ISystemdLibc;
|
|
81
|
+
/** The `msg_namelen` of an `AF_UNIX` address: a path keeps its NUL; an abstract name has none. */
|
|
82
|
+
export declare const socketAddressLength: (addressArg: string) => number;
|
|
83
|
+
/** Writes a `sockaddr_un` at `offsetArg`; an abstract name's leading `@` becomes its NUL. */
|
|
84
|
+
export declare const writeSocketAddress: (bufferArg: Buffer, offsetArg: number, addressArg: string) => void;
|
|
85
|
+
/** `CMSG_SPACE` for `countArg` descriptors. */
|
|
86
|
+
export declare const controlSpace: (countArg: number) => number;
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { SystemdRuntimeError } from './classes.systemdruntimeerror.js';
|
|
2
|
+
/** The first Node.js major with `node:ffi`, which this module calls libc through. */
|
|
3
|
+
export const systemdRuntimeNodeMajor = 26;
|
|
4
|
+
/** Internal: refuses a Node.js older than `systemdRuntimeNodeMajor`; the subpath runs it on import. */
|
|
5
|
+
export const assertSystemdRuntimeNode = (versionArg = process.versions.node) => {
|
|
6
|
+
const major = Number(/^(\d+)\./.exec(versionArg)?.[1]);
|
|
7
|
+
if (!(major >= systemdRuntimeNodeMajor)) {
|
|
8
|
+
throw new SystemdRuntimeError('runtime_unsupported', `@push.rocks/smartdaemon/systemd-runtime requires Node.js ${systemdRuntimeNodeMajor} or later; this is Node.js ${versionArg}.`);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The generic Linux values both qualified targets (x86_64 and aarch64, glibc) use. The structure
|
|
13
|
+
* layouts below are the LP64 glibc ones, identical on both:
|
|
14
|
+
*
|
|
15
|
+
* - `sockaddr_un`: `sa_family_t` (u16) at 0, `sun_path[108]` at 2.
|
|
16
|
+
* - `iovec` (16 bytes): `iov_base` at 0, `iov_len` at 8.
|
|
17
|
+
* - `msghdr` (56 bytes): `msg_name` at 0, `msg_namelen` (u32) at 8, `msg_iov` at 16, `msg_iovlen`
|
|
18
|
+
* at 24, `msg_control` at 32, `msg_controllen` at 40, `msg_flags` at 48.
|
|
19
|
+
* - `cmsghdr`: `cmsg_len` (size_t) at 0, `cmsg_level` at 8, `cmsg_type` at 12, data at 16;
|
|
20
|
+
* `CMSG_LEN(n)` is 16 + n and `CMSG_SPACE(n)` 16 + n rounded up to 8.
|
|
21
|
+
* - `timespec` (16 bytes): `tv_sec` at 0, `tv_nsec` at 8.
|
|
22
|
+
* - `rlimit` (16 bytes): `rlim_cur` (u64) at 0, `rlim_max` (u64) at 8; `RLIM_INFINITY` is all ones.
|
|
23
|
+
*/
|
|
24
|
+
export const libcConstants = {
|
|
25
|
+
AF_UNIX: 1,
|
|
26
|
+
SOCK_DGRAM: 2,
|
|
27
|
+
SOCK_CLOEXEC: 0o2000000,
|
|
28
|
+
SOL_SOCKET: 1,
|
|
29
|
+
SCM_RIGHTS: 1,
|
|
30
|
+
MSG_NOSIGNAL: 0x4000,
|
|
31
|
+
F_GETFD: 1,
|
|
32
|
+
F_SETFD: 2,
|
|
33
|
+
FD_CLOEXEC: 1,
|
|
34
|
+
CLOCK_MONOTONIC: 1,
|
|
35
|
+
EINTR: 4,
|
|
36
|
+
RLIMIT_NOFILE: 7,
|
|
37
|
+
};
|
|
38
|
+
/** `sun_path` is 108 bytes; an address of up to 107 bytes keeps a path's terminating NUL. */
|
|
39
|
+
export const socketAddressMaximumBytes = 107;
|
|
40
|
+
/** The kernel's `SCM_MAX_FD`: the most descriptors one `SCM_RIGHTS` message carries. */
|
|
41
|
+
export const descriptorsPerMessageMaximum = 253;
|
|
42
|
+
const libcFunctions = {
|
|
43
|
+
socket: { arguments: ['int32', 'int32', 'int32'], return: 'int32' },
|
|
44
|
+
sendmsg: { arguments: ['int32', 'pointer', 'int32'], return: 'int64' },
|
|
45
|
+
close: { arguments: ['int32'], return: 'int32' },
|
|
46
|
+
// fcntl(2) is variadic; its third argument is an int for F_GETFD and F_SETFD.
|
|
47
|
+
fcntl: { arguments: ['int32', 'int32', 'int32'], return: 'int32' },
|
|
48
|
+
clock_gettime: { arguments: ['int32', 'pointer'], return: 'int32' },
|
|
49
|
+
getrlimit: { arguments: ['int32', 'pointer'], return: 'int32' },
|
|
50
|
+
__errno_location: { arguments: [], return: 'pointer' },
|
|
51
|
+
};
|
|
52
|
+
let loaded = null;
|
|
53
|
+
/**
|
|
54
|
+
* glibc, opened through `node:ffi` on first use and kept for the process lifetime. Loading
|
|
55
|
+
* `node:ffi` emits Node's ExperimentalWarning once.
|
|
56
|
+
*/
|
|
57
|
+
export const systemdLibc = () => {
|
|
58
|
+
if (loaded !== null)
|
|
59
|
+
return loaded;
|
|
60
|
+
if (process.platform !== 'linux' || (process.arch !== 'x64' && process.arch !== 'arm64')) {
|
|
61
|
+
throw new SystemdRuntimeError('runtime_unsupported', `The systemd runtime supports Linux on x64 and arm64; this is ${process.platform} on ${process.arch}.`);
|
|
62
|
+
}
|
|
63
|
+
const ffiModule = process.getBuiltinModule('node:ffi');
|
|
64
|
+
if (ffiModule === undefined) {
|
|
65
|
+
throw new SystemdRuntimeError('runtime_unsupported', 'node:ffi is not available (disabled by --no-experimental-ffi?).');
|
|
66
|
+
}
|
|
67
|
+
let functions;
|
|
68
|
+
try {
|
|
69
|
+
functions = ffiModule.dlopen('libc.so.6', libcFunctions).functions;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new SystemdRuntimeError('runtime_unsupported', 'glibc (libc.so.6) could not be opened through node:ffi; under the permission model pass --allow-ffi.', { cause: error });
|
|
73
|
+
}
|
|
74
|
+
loaded = Object.freeze({
|
|
75
|
+
functions,
|
|
76
|
+
ffi: ffiModule,
|
|
77
|
+
errno: () => ffiModule.getInt32(functions.__errno_location(), 0),
|
|
78
|
+
});
|
|
79
|
+
return loaded;
|
|
80
|
+
};
|
|
81
|
+
/** The `msg_namelen` of an `AF_UNIX` address: a path keeps its NUL; an abstract name has none. */
|
|
82
|
+
export const socketAddressLength = (addressArg) => 2 + Buffer.byteLength(addressArg, 'utf8') + (addressArg.startsWith('/') ? 1 : 0);
|
|
83
|
+
/** Writes a `sockaddr_un` at `offsetArg`; an abstract name's leading `@` becomes its NUL. */
|
|
84
|
+
export const writeSocketAddress = (bufferArg, offsetArg, addressArg) => {
|
|
85
|
+
bufferArg.writeUInt16LE(libcConstants.AF_UNIX, offsetArg);
|
|
86
|
+
bufferArg.write(addressArg, offsetArg + 2, 'utf8');
|
|
87
|
+
if (addressArg.startsWith('@'))
|
|
88
|
+
bufferArg[offsetArg + 2] = 0;
|
|
89
|
+
};
|
|
90
|
+
/** `CMSG_SPACE` for `countArg` descriptors. */
|
|
91
|
+
export const controlSpace = (countArg) => 16 + ((4 * countArg + 7) & ~7);
|
|
92
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3lzdGVtZHJ1bnRpbWUubGliYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3N5c3RlbWRydW50aW1lL3N5c3RlbWRydW50aW1lLmxpYmMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFFdkUscUZBQXFGO0FBQ3JGLE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLEVBQUUsQ0FBQztBQUUxQyx1R0FBdUc7QUFDdkcsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxVQUFVLEdBQVcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQVEsRUFBRTtJQUMzRixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsSUFBSSxDQUFDLENBQUMsS0FBSyxJQUFJLHVCQUF1QixDQUFDLEVBQUUsQ0FBQztRQUN4QyxNQUFNLElBQUksbUJBQW1CLENBQzNCLHFCQUFxQixFQUNyQiw0REFBNEQsdUJBQXVCLDhCQUE4QixVQUFVLEdBQUcsQ0FDL0gsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUc7SUFDM0IsT0FBTyxFQUFFLENBQUM7SUFDVixVQUFVLEVBQUUsQ0FBQztJQUNiLFlBQVksRUFBRSxTQUFTO0lBQ3ZCLFVBQVUsRUFBRSxDQUFDO0lBQ2IsVUFBVSxFQUFFLENBQUM7SUFDYixZQUFZLEVBQUUsTUFBTTtJQUNwQixPQUFPLEVBQUUsQ0FBQztJQUNWLE9BQU8sRUFBRSxDQUFDO0lBQ1YsVUFBVSxFQUFFLENBQUM7SUFDYixlQUFlLEVBQUUsQ0FBQztJQUNsQixLQUFLLEVBQUUsQ0FBQztJQUNSLGFBQWEsRUFBRSxDQUFDO0NBQ1IsQ0FBQztBQUVY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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** sd_listen_fds(3): `SD_LISTEN_FDS_START`, the first passed descriptor. */
|
|
2
|
+
export declare const systemdListenDescriptorsStart = 3;
|
|
3
|
+
export interface ISystemdProcessEnvironmentOptions {
|
|
4
|
+
/** The environment to read; `process.env` by default. */
|
|
5
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
6
|
+
/** The process the variables must name; `process.pid` by default. */
|
|
7
|
+
readonly pid?: number;
|
|
8
|
+
}
|
|
9
|
+
/** One descriptor the service manager passed: its number and its `LISTEN_FDNAMES` entry. */
|
|
10
|
+
export interface ISystemdListenDescriptor {
|
|
11
|
+
readonly descriptor: number;
|
|
12
|
+
/** The `FDNAME=` it was stored under, the socket unit's `FileDescriptorName=`, or `unknown`. */
|
|
13
|
+
readonly name: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Marks one open descriptor close-on-exec (`fcntl(F_SETFD, FD_CLOEXEC)`) and verifies the flag,
|
|
17
|
+
* so no child process inherits it. Throws `close_on_exec_failed` with `errno` when the descriptor
|
|
18
|
+
* is not open or the flag does not hold.
|
|
19
|
+
*/
|
|
20
|
+
export declare const setCloseOnExec: (descriptorArg: number) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Takes the descriptors the service manager passed this process (sd_listen_fds_with_names(3)):
|
|
23
|
+
* socket-activation sockets and descriptor-store entries, numbered from 3.
|
|
24
|
+
*
|
|
25
|
+
* `LISTEN_PID`, `LISTEN_FDS` and `LISTEN_FDNAMES` always leave the environment, so no child sees
|
|
26
|
+
* them. Without them, or with `LISTEN_PID` naming another process (variables inherited from a
|
|
27
|
+
* parent), it returns an empty list and touches no descriptor. For this process every passed
|
|
28
|
+
* descriptor is marked close-on-exec before the list returns. Without `LISTEN_FDNAMES` each name is
|
|
29
|
+
* `unknown`, as in systemd.
|
|
30
|
+
*
|
|
31
|
+
* Throws `listen_environment_invalid` before touching any descriptor for a partial or malformed set
|
|
32
|
+
* (a count that is not a positive integer, a count whose last descriptor, `2 + count`, is at or
|
|
33
|
+
* above the process's hard `RLIMIT_NOFILE`, a names list whose length differs from the count, an
|
|
34
|
+
* invalid name), and with `errno` when `getrlimit(2)` fails. Descriptors are then marked one by one
|
|
35
|
+
* from 3, and memory grows only with descriptors proven open: the first passed descriptor that is
|
|
36
|
+
* not open throws `close_on_exec_failed`, as `sd_listen_fds(3)` fails on it; descriptors before it
|
|
37
|
+
* keep the flag.
|
|
38
|
+
*/
|
|
39
|
+
export declare const takeSystemdListenDescriptors: (optionsArg?: ISystemdProcessEnvironmentOptions) => readonly ISystemdListenDescriptor[];
|
|
40
|
+
/**
|
|
41
|
+
* The watchdog interval the manager expects `WATCHDOG=1` within (`WATCHDOG_USEC`, sd_watchdog_enabled(3)),
|
|
42
|
+
* in microseconds; null when the unit has no watchdog or `WATCHDOG_PID` names another process.
|
|
43
|
+
* Reads the environment without changing it. Throws `watchdog_environment_invalid` for a malformed
|
|
44
|
+
* value.
|
|
45
|
+
*/
|
|
46
|
+
export declare const watchdogIntervalUsec: (optionsArg?: ISystemdProcessEnvironmentOptions) => number | null;
|