Skip to content

Commit

Permalink
feat: when sigkill is used use taskkill on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
alextekartik committed Oct 29, 2024
1 parent 38da516 commit 830089d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 12 deletions.
11 changes: 10 additions & 1 deletion packages/process_run/doc/shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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.
38 changes: 27 additions & 11 deletions packages/process_run/lib/src/shell.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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 <processID> 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;
Expand Down

0 comments on commit 830089d

Please sign in to comment.