ZetCode

Dart ProcessSignal

最后修改于 2025 年 4 月 4 日

Dart 中的 ProcessSignal 类提供了一种处理操作系统进程信号的方法。它允许优雅地关闭和自定义信号处理。

进程信号是操作系统发送给程序的通知。常见的信号包括 SIGINT (Ctrl+C) 和 SIGTERM (终止请求)。

基本定义

ProcessSignal 代表可以发送给进程的操作系统信号。它是 Dart 的 dart:io 库的一部分,用于服务器端应用程序。

主要功能包括信号监视、优雅关闭处理和特定于平台的信号支持。并非所有信号在所有平台上都可用。

处理 SIGINT (Ctrl+C)

此示例显示了 Dart 中基本的 SIGINT (Ctrl+C) 信号处理。

main.dart
import 'dart:io';

void main() async {
  ProcessSignal.sigint.watch().listen((signal) {
    print('\nReceived SIGINT (signal $signal)');
    print('Performing cleanup...');
    exit(0);
  });

  print('Press Ctrl+C to send SIGINT');
  await Future.delayed(Duration(minutes: 1));
}

我们为 SIGINT 信号设置了一个监听器。当按下 Ctrl+C 时,我们的处理程序将在退出前执行清理代码。程序等待用户输入。

$ dart main.dart
Press Ctrl+C to send SIGINT
^C
Received SIGINT (signal ProcessSignal_SIGINT)
Performing cleanup...

处理多个信号

此示例演示了如何使用一个监听器处理多个信号。

main.dart
import 'dart:io';

void main() async {
  final signals = [ProcessSignal.sigterm, ProcessSignal.sighup];
  
  for (var signal in signals) {
    signal.watch().listen((_) {
      print('Received ${signal.toString()}');
      exit(0);
    });
  }

  print('Running (PID: ${pid})');
  print('Send SIGTERM or SIGHUP to terminate');
  await Future.delayed(Duration(minutes: 1));
}

我们为 SIGTERM 和 SIGHUP 信号都创建了监听器。任何一个信号都会触发相同的关闭过程。程序显示其进程 ID。

$ dart main.dart
Running (PID: 12345)
Send SIGTERM or SIGHUP to terminate
Received ProcessSignal_SIGTERM

优雅关闭

此示例实现了带有清理操作的优雅关闭。

main.dart
import 'dart:io';

class Server {
  Future<void> cleanup() async {
    print('Closing database connections...');
    await Future.delayed(Duration(seconds: 1));
    print('Saving state...');
    await Future.delayed(Duration(seconds: 1));
    print('Cleanup complete');
  }
}

void main() async {
  final server = Server();
  
  ProcessSignal.sigterm.watch().listen((_) async {
    print('\nShutdown initiated');
    await server.cleanup();
    exit(0);
  });

  print('Server running (PID: ${pid})');
  print('Send SIGTERM to terminate gracefully');
  await Future.delayed(Duration(minutes: 1));
}

我们创建了一个带有清理操作的服务器类。当收到 SIGTERM 时,它会在退出前执行异步清理。这确保了数据完整性。

$ dart main.dart
Server running (PID: 12345)
Send SIGTERM to terminate gracefully
Shutdown initiated
Closing database connections...
Saving state...
Cleanup complete

忽略信号

此示例展示了如何在应用程序中忽略特定信号。

main.dart
import 'dart:io';

void main() async {
  // Ignore SIGINT (Ctrl+C)
  ProcessSignal.sigint.watch().listen((_) {
    print('\nSIGINT ignored (use SIGTERM to terminate)');
  });

  ProcessSignal.sigterm.watch().listen((_) {
    print('\nReceived SIGTERM - shutting down');
    exit(0);
  });

  print('Running (PID: ${pid})');
  print('Try Ctrl+C - it will be ignored');
  await Future.delayed(Duration(minutes: 1));
}

我们忽略 SIGINT (Ctrl+C),但仍然处理 SIGTERM。这创建了一个更受控制的关闭过程,需要特定的终止信号。

$ dart main.dart
Running (PID: 12345)
Try Ctrl+C - it will be ignored
^C
SIGINT ignored (use SIGTERM to terminate)
Received SIGTERM - shutting down

特定于平台的信号

此示例演示了 Dart 中特定于平台的信号处理。

main.dart
import 'dart:io';

void main() async {
  // Platform-specific signals
  final signals = [
    if (Platform.isLinux || Platform.isMacOS) ProcessSignal.sigusr1,
    if (Platform.isWindows) ProcessSignal.sigbreak,
  ];

  for (var signal in signals) {
    signal.watch().listen((_) {
      print('Received ${signal.toString()}');
      // Custom handling for each signal
    });
  }

  print('Running on ${Platform.operatingSystem}');
  print('Send platform-specific signals');
  await Future.delayed(Duration(minutes: 1));
}

我们根据平台处理不同的信号。Linux/macOS 使用 SIGUSR1,而 Windows 使用 SIGBREAK。代码会适应当前平台。

$ dart main.dart
Running on linux
Send platform-specific signals
Received ProcessSignal_SIGUSR1

最佳实践

来源

Dart ProcessSignal 文档

本教程通过实际示例介绍了 Dart 的 ProcessSignal 类,展示了信号处理、优雅关闭和特定于平台的注意事项。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有超过十年的经验。

列出 所有 Dart 教程