plum-e2e 2.6.5 → 2.6.6
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.
|
@@ -250,6 +250,40 @@ function stopNode(id, fallbackPort = null) {
|
|
|
250
250
|
return signalled;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
/**
|
|
254
|
+
* Frees a TCP port by killing whatever process is bound to it, so Start can't
|
|
255
|
+
* fail with EADDRINUSE against a stale/orphaned process this manager lost
|
|
256
|
+
* track of (e.g. one that ignored SIGTERM from a previous stop, or was never
|
|
257
|
+
* in the registry to begin with). SIGTERM first, escalating to SIGKILL if the
|
|
258
|
+
* process is still alive after a short grace period.
|
|
259
|
+
*
|
|
260
|
+
* Returns true if a process was found (and signalled), false if the port was
|
|
261
|
+
* already free.
|
|
262
|
+
*/
|
|
263
|
+
async function killPort(port) {
|
|
264
|
+
let pid = findPidOnPort(port);
|
|
265
|
+
if (!pid) return false;
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
process.kill(pid, 'SIGTERM');
|
|
269
|
+
} catch {}
|
|
270
|
+
|
|
271
|
+
const deadline = Date.now() + 2000;
|
|
272
|
+
while (Date.now() < deadline && isAlive(pid)) {
|
|
273
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
pid = findPidOnPort(port);
|
|
277
|
+
if (pid && isAlive(pid)) {
|
|
278
|
+
try {
|
|
279
|
+
process.kill(pid, 'SIGKILL');
|
|
280
|
+
} catch {}
|
|
281
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
|
|
253
287
|
module.exports = {
|
|
254
288
|
BACKEND_DIR,
|
|
255
289
|
LOGS_DIR,
|
|
@@ -260,6 +294,7 @@ module.exports = {
|
|
|
260
294
|
isLocalUrl,
|
|
261
295
|
parsePort,
|
|
262
296
|
findPidOnPort,
|
|
297
|
+
killPort,
|
|
263
298
|
pruneDead,
|
|
264
299
|
statusOf,
|
|
265
300
|
prepareEnv,
|
|
@@ -40,7 +40,8 @@ const {
|
|
|
40
40
|
prepareEnv,
|
|
41
41
|
startNode,
|
|
42
42
|
stopNode,
|
|
43
|
-
findPidOnPort
|
|
43
|
+
findPidOnPort,
|
|
44
|
+
killPort
|
|
44
45
|
} = runnerProcess;
|
|
45
46
|
const { generateToken, registerWithPrimary, detectLanIp } = nodeRegister;
|
|
46
47
|
|
|
@@ -206,12 +207,18 @@ async function runAction(r) {
|
|
|
206
207
|
const port = parsePort(r.url);
|
|
207
208
|
|
|
208
209
|
if (action === 'start') {
|
|
210
|
+
const s = clack.spinner();
|
|
211
|
+
s.start(`Freeing port ${port}...`);
|
|
212
|
+
const killed = await killPort(Number(port));
|
|
213
|
+
s.stop(killed ? pc.dim(`Freed port ${port}`) : pc.dim(`Port ${port} was already free`));
|
|
214
|
+
|
|
209
215
|
prepareNodeEnv();
|
|
210
216
|
const entry = startNode({ id: r.id, port, token: r.token });
|
|
211
217
|
clack.log.success(pc.green(`Started "${r.name}" on port ${port} (pid ${entry.pid})`));
|
|
212
218
|
} else if (action === 'stop') {
|
|
213
219
|
if (r.managed) {
|
|
214
220
|
const ok = stopNode(r.id);
|
|
221
|
+
await killPort(Number(port));
|
|
215
222
|
clack.log.success(
|
|
216
223
|
ok ? pc.green(`Stopped "${r.name}"`) : pc.dim(`"${r.name}" was not running`)
|
|
217
224
|
);
|
|
@@ -223,6 +230,11 @@ async function runAction(r) {
|
|
|
223
230
|
s.stop(pc.green(`Stopped "${r.name}"`));
|
|
224
231
|
} catch (e) {
|
|
225
232
|
s.stop(pc.red(`Could not stop "${r.name}": ${e.message}`));
|
|
233
|
+
} finally {
|
|
234
|
+
// Belt-and-suspenders: if this runner happens to be local (or
|
|
235
|
+
// the network shutdown call above silently failed), make sure
|
|
236
|
+
// nothing is left bound to its port.
|
|
237
|
+
await killPort(Number(port));
|
|
226
238
|
}
|
|
227
239
|
}
|
|
228
240
|
} else if (action === 'restart') {
|
|
@@ -230,7 +242,7 @@ async function runAction(r) {
|
|
|
230
242
|
const s = clack.spinner();
|
|
231
243
|
s.start(`Restarting "${r.name}"...`);
|
|
232
244
|
stopNode(r.id);
|
|
233
|
-
await
|
|
245
|
+
await killPort(Number(port));
|
|
234
246
|
const entry = startNode({ id: r.id, port, token: r.token });
|
|
235
247
|
s.stop(pc.green(`Restarted "${r.name}" (pid ${entry.pid})`));
|
|
236
248
|
} else {
|