From 830089d3c41e4f07cb3d72be3b0db8dbbd9e81ec Mon Sep 17 00:00:00 2001 From: Alexandre Roux Date: Tue, 29 Oct 2024 15:12:14 +0100 Subject: [PATCH] feat: when sigkill is used use taskkill on Windows --- packages/process_run/doc/shell.md | 11 ++++++- packages/process_run/lib/src/shell.dart | 38 ++++++++++++++++++------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/packages/process_run/doc/shell.md b/packages/process_run/doc/shell.md index 3ad5161..d3d7072 100644 --- a/packages/process_run/doc/shell.md +++ b/packages/process_run/doc/shell.md @@ -96,7 +96,7 @@ $ alias ds='dart pub global run process_run:shell' ### Helper -`ShellLinesController` allows listeninging line from a command line script. +`ShellLinesController` allows listening line from a command line script. ```dart var controller = ShellLinesController(); @@ -202,3 +202,12 @@ Then run your commands via `osascript` like so: ``` That will prompt for the user to type his password and then will run the script. + +### Killing a shell + +You can kill a shell using the `kill()` method. It will kill the shell and all its spawn children. +By default its uses `ProcessSignal.sigterm` signal. You can specify a different signal using the `signal` parameter. + +A special trick is made when `ProcessSignal.sigkill` used as it will force killing all children processes on Windows (taskkill), MacOS and Linux (pkill). +As I was experiencing with `dhttpd`, killing the process was not really killing the server so using `sigkill` (and so taskkill and pkill) was properly +killing the server. diff --git a/packages/process_run/lib/src/shell.dart b/packages/process_run/lib/src/shell.dart index d4eabd1..7c48c47 100644 --- a/packages/process_run/lib/src/shell.dart +++ b/packages/process_run/lib/src/shell.dart @@ -297,19 +297,35 @@ abstract class Shell implements ShellCore, ShellCoreSync { io.stderr.writeln( 'killing $_killedRunId, ${_currentProcessToString()} signal $_killedProcessSignal'); - /// Workaround for linux when using sigkill to kill the children processes too - if ((io.Platform.isLinux || io.Platform.isMacOS) && - _killedProcessSignal == ProcessSignal.sigkill) { - try { - /// Kill the children - var pid = _currentProcess!.pid; - // Kill children process - runExecutableArgumentsSync('pkill', ['-P', '$pid']); - } catch (_) {} + if (_killedProcessSignal == ProcessSignal.sigkill) { + var pid = _currentProcess!.pid; + + /// Workaround when using sigkill to kill the children processes too + if (io.Platform.isLinux || io.Platform.isMacOS) { + try { + /// Kill the children + runExecutableArgumentsSync('pkill', ['-P', '$pid']); + } catch (_) {} + } else if (io.Platform.isWindows) { + try { + /// Kill the children + var pid = _currentProcess!.pid; + // Kill children process + // /pid Specifies the process ID of the process to be terminated. + // /f Specifies that processes be forcefully ended. This parameter is ignored for remote processes; all remote processes are forcefully ended. + // /t Ends the specified process and any child processes started by it. + runExecutableArgumentsSync( + 'taskkill', ['/t', '/f', '/pid', '$pid']); + } catch (_) {} + } } - /// kill the parent process - result = _currentProcess!.kill(_killedProcessSignal); + try { + /// kill the parent process + result = _currentProcess!.kill(_killedProcessSignal); + } catch (_) { + result = false; + } _clearPreviousContext(); } catch (_) { result = false;