diff --git a/src/apps.js b/src/apps.js index 046341d0b..420853846 100644 --- a/src/apps.js +++ b/src/apps.js @@ -2050,7 +2050,7 @@ async function getLogs(app, options) { const cp = logs.tail(logPaths, { lines: options.lines, follow: options.follow }); const logStream = new logs.LogStream({ format: options.format || 'json', source: appId }); - logStream.close = cp.kill.bind(cp, 'SIGTERM'); // hook for caller. closing stream kills the child process + logStream.close = cp.terminate; // closing stream kills the child process cp.stdout.pipe(logStream); diff --git a/src/services.js b/src/services.js index ba4c971c6..9c01a806e 100644 --- a/src/services.js +++ b/src/services.js @@ -474,7 +474,7 @@ async function getServiceLogs(id, options) { } const logStream = new logs.LogStream({ format: options.format || 'json', source: name }); - logStream.close = cp.kill.bind(cp, 'SIGTERM'); // closing stream kills the child process + logStream.close = cp.terminate; // closing stream kills the child process cp.stdout.pipe(logStream); diff --git a/src/shell.js b/src/shell.js index 0680bee78..83100e816 100644 --- a/src/shell.js +++ b/src/shell.js @@ -100,7 +100,18 @@ function sudo(tag, args, options, callback) { callback(e); }); + // sudo forks and execs the program. sudo also hangs around as the parent of the program waiting on the program and also forwarding signals. + // sudo does not forward signals when the originator comes from the same process group. recently, there has been a change where it will + // forward signals as long as sudo or the command is not the group leader (https://www.sudo.ws/repos/sudo/rev/d1bf60eac57f) + // for us, this means that calling kill from this node process doesn't work since it's in the same group (and ubuntu 22 doesn't have the above fix). + // the workaround is to invoke a kill from a different process group and this is done by starting detached + // another idea is: use "ps --pid cp.pid -o pid=" to get the pid of the command and then send it signal directly + cp.terminate = function () { + child_process.spawn('kill', ['-SIGTERM', cp.pid], { detached: true }, (error) => { if (error) debug(`${tag} could not terminate`, error); }); + }; + cp.stdin.end(); if (options.onMessage) cp.on('message', options.onMessage); + return cp; } diff --git a/src/system.js b/src/system.js index 99c31727d..5add78ec7 100644 --- a/src/system.js +++ b/src/system.js @@ -321,7 +321,7 @@ async function getLogs(unit, options) { const cp = logs.tail([logFile], { lines: options.lines, follow: options.follow }); const logStream = new logs.LogStream({ format: options.format || 'json', source: unit }); - logStream.close = cp.kill.bind(cp, 'SIGKILL'); // hook for caller. closing stream kills the child process + logStream.close = cp.terminate; // closing stream kills the child process cp.stdout.pipe(logStream); diff --git a/src/tasks.js b/src/tasks.js index 80fca4903..bfd839cda 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -277,7 +277,7 @@ async function getLogs(task, options) { const cp = logs.tail([`${paths.TASKS_LOG_DIR}/${task.id}.log`], { lines: options.lines, follow: options.follow }); const logStream = new logs.LogStream({ format: options.format || 'json', source: task.id }); - logStream.close = cp.kill.bind(cp, 'SIGKILL'); // hook for caller. closing stream kills the child process + logStream.close = cp.terminate; // closing stream kills the child process cp.stdout.pipe(logStream);