Signals in Dart

Here’s the translation of the Go code to Dart, with explanations in Markdown format suitable for Hugo:

Sometimes we’d like our Dart programs to intelligently handle system signals. For example, we might want a server to gracefully shutdown when it receives a SIGTERM, or a command-line tool to stop processing input if it receives a SIGINT. Here’s how to handle signals in Dart using streams.

import 'dart:async';
import 'dart:io';

void main() {
  // Dart signal handling works by listening to a Stream of ProcessSignal
  // objects. We'll create a StreamController to manage these notifications.
  final sigs = StreamController<ProcessSignal>();

  // Register the signals we want to listen for
  ProcessSignal.sigint.watch().listen(sigs.add);
  ProcessSignal.sigterm.watch().listen(sigs.add);

  // We could listen to `sigs` here in the main function, but let's see how 
  // this could also be done in a separate asynchronous function, to demonstrate
  // a more realistic scenario of graceful shutdown.
  final done = Completer<bool>();

  // This asynchronous function listens for signals. When it gets one,
  // it'll print it out and then notify the program that it can finish.
  () async {
    final sig = await sigs.stream.first;
    print('');
    print(sig);
    done.complete(true);
  }();

  // The program will wait here until it gets the expected signal
  // (as indicated by the asynchronous function above completing the Future)
  // and then exit.
  print('awaiting signal');
  done.future.then((_) {
    print('exiting');
    exit(0);
  });
}

When we run this program it will block waiting for a signal. By typing ctrl-C (which the terminal shows as ^C) we can send a SIGINT signal, causing the program to print SIGINT and then exit.

$ dart run signals.dart
awaiting signal
^C
SIGINT
exiting

In Dart, we use the ProcessSignal class to handle system signals. Instead of channels, we use Dart’s Stream and StreamController for asynchronous event handling. The Completer class is used to create a Future that can be completed later, similar to how channels are used in the original example.

Note that signal handling in Dart may vary depending on the platform, and some signals might not be available on all systems. Always test your signal handling code on the target platforms where your application will run.