Description
When running dart run main.dart
handling sigint
in main.dart
will cause the dartdev
process to die, while the child process lives on.
The following sample handles sigint
.
Future<void> main() async {
var count = 0;
ProcessSignal.sigint.watch().forEach((s) {
count++;
print('child: Got a SIGINT $count times, hit it 3 times to terminate');
if (count >= 3) {
exit(0);
}
});
print('child: Sleep 5s');
await Future.delayed(Duration(seconds: 5));
print('child: 5 sec done.');
exit(55);
}
Correct behavior: when invoking dart main.dart
and sending sigint
(by hitting control+c
) we get the following correct behavior:
[sdk]$./out/ReleaseX64/dart-sdk/bin/dart main.dart
child: Sleep 5s
^Cchild: Got a SIGINT 1 times, hit it 3 times to terminate
^Cchild: Got a SIGINT 2 times, hit it 3 times to terminate
child: 5 sec done.
[sdk]$
Incorrect behavior: when invoking dart run main.dart
and sending sigint
(by hitting control+c
) we get the following incorrect behavior:
[sdk]$./out/ReleaseX64/dart-sdk/bin/dart run main.dart
child: Sleep 5s
^C
[sdk]$child: Got a SIGINT 1 times, hit it 3 times to terminate
child: 5 sec done.
(the empty line at the end is how the shell is left on my system)
Notice that:
- The parent process dies before the child, because
control+c
sendssigint
to the process-group and while the child handles it, the parent does not. - The shell thinks the prompt is back before the child is terminated.
- To get a working a working shell the user has to interrupt again.
If scripting or using dart run
as a subprocess from another program the signal is likely to be sent to the dartdev
parent process only, again this would terminate the parent and leave the child alive.
/cc @sigurdm, who is also interested. So far we've avoided the issue in pub run
by using isolates.