在开发板ubuntu 18.04 arm64上调试部署modbus边缘采集的communicator模块,遇到进程没有优雅的退出,线程的清理工作没有完成。
需求:
- 在开发环境中,在终端中手动运行程序,ctrl+c结束进程,所有线程都需要执行清理工作后进程退出
- 在生产环境中,将程序部署为ubuntu的服务,通过systemctl stop命令结束进程,所有线程都需要执行清理工作后进程退出
问题1:在终端中手动运行程序,然后ctrl+c,程序没有优雅的退出,所有线程都没有执行清理工作。
解决办法:在linux终端中按下ctrl+c,系统会给正在运行的进程发送SIGINT信号,在代码中处理SIGINT信号,让子线程响应该信号,从而完成退出的工作
signal(SIGINT, sigint_handler);
QSignalMapper signalMapper;
QObject::connect(&a, &QCoreApplication::aboutToQuit, &signalMapper, QOverload<>::of(&QSignalMapper::map));
signalMapper.setMapping(&a, SIGTERM);
QObject::connect(&signalMapper, QOverload<int>::of(&QSignalMapper::mapped), &a, &QCoreApplication::quit);
问题2:通过systemctl stop命令结束进程,查看journalctl日志,所有线程没有执行清理工作(应该是来不及执行清理工作)
解决办法:systemctl stop命令,系统默认会给正在运行的服务进程发送SIGTERM信号,在代码中处理SIGTERM信号,让子线程响应该信号,从而完成退出的工作
signal(SIGINT, sigint_handler);
signal(SIGTERM, sigint_handler);
QSignalMapper signalMapper;
QObject::connect(&a, &QCoreApplication::aboutToQuit, &signalMapper, QOverload<>::of(&QSignalMapper::map));
signalMapper.setMapping(&a, SIGINT);
signalMapper.setMapping(&a, SIGTERM);
QObject::connect(&signalMapper, QOverload<int>::of(&QSignalMapper::mapped), &a, &QCoreApplication::quit);
总结:
chatGPT:
Ctrl+C
组合键在 Linux 终端中用来发送 SIGINT 信号给正在运行的进程,以请求其终止。这是 Linux 系统的一个通用行为,不受具体的发行版影响。SIGINT 信号是中断信号,通常被用来请求进程优雅地终止,允许它执行清理工作。
systemctl stop
命令默认会发送 SIGTERM 信号给指定的系统服务,请求其优雅地终止。这与Ctrl+C
发送的 SIGINT 信号有所不同。SIGTERM 信号也是一种终止信号,但与 SIGINT 不同,它是正常的终止请求,不会中断进程的执行,而是让进程在收到信号后自行进行清理工作并安全地关闭。
Gemini:
SIGTERM 和 SIGINT 都是用于通知进程终止的信号,但它们之间存在一些关键差异:
产生方式:
- SIGINT: 通常由用户按下键盘上的 Ctrl+C 键产生。
- SIGTERM: 可以通过以下几种方式产生:
- 使用
kill
命令向进程发送信号。- 由其他进程发送。
- 由系统本身发送,例如当系统资源不足时。
默认行为:
- SIGINT: 通常会导致前台进程立即终止。
- SIGTERM: 会导致进程以 正常 方式终止。这意味着进程应该有机会进行清理工作,例如关闭打开的文件和释放资源。
可控性:
- SIGINT: 通常 不可控。这意味着进程无法捕获或忽略 SIGINT 信号。
- SIGTERM: 通常 可控。这意味着进程可以捕获和处理 SIGTERM 信号。例如,进程可以选择忽略 SIGTERM 信号,或者在终止之前执行一些清理工作。
强制性:
- SIGINT: 是一个 非强制 信号。这意味着进程可以选择忽略 SIGINT 信号并继续运行。
- SIGTERM: 是一个 软 信号。这意味着进程通常会响应 SIGTERM 信号并终止,但它 可以选择 忽略该信号。
SIGKILL 信号:
值得注意的是,还存在 SIGKILL 信号,它与 SIGTERM 和 SIGINT 信号不同。SIGKILL 是一个 硬 信号,这意味着进程 无法 忽略它。SIGKILL 信号用于在进程无响应 SIGTERM 信号或其他终止信号的情况下强制终止进程。