【发布时间】:2021-12-29 03:48:36
【问题描述】:
我有以下 C++ 代码:
#include <signal>
#include <iostream>
void sig_handler(int signo, siginfo_t *info, void *_ctx) {
cout << "HANDLE AND RESET!!" << endl;
// try to forward the signal.
raise(info->si_signo);
// terminate the process immediately.
puts("watf? exit");
_exit(EXIT_FAILURE);
}
void registerSignalHandlers() {
vector<int> signals = {
// Signals for which the default action is "Core".
SIGABRT, // Abort signal from abort(3)
SIGBUS, // Bus error (bad memory access)
SIGFPE, // Floating point exception
SIGILL, // Illegal Instruction
SIGIOT, // IOT trap. A synonym for SIGABRT
SIGQUIT, // Quit from keyboard
SIGSEGV, // Invalid memory reference
SIGSYS, // Bad argument to routine (SVr4)
SIGTRAP, // Trace/breakpoint trap
SIGXCPU, // CPU time limit exceeded (4.2BSD)
SIGXFSZ, // File size limit exceeded (4.2BSD)
SIGTERM
};
for (size_t i = 0; i < signals.size(); ++i) {
struct sigaction action;
memset(&action, 0, sizeof action);
action.sa_flags = static_cast<int>(SA_SIGINFO | SA_ONSTACK | SA_NODEFER | SA_RESETHAND);
sigfillset(&action.sa_mask);
sigdelset(&action.sa_mask, signals[i]);
action.sa_sigaction = &sig_handler;
int r = sigaction(signals[i], &action, nullptr);
}
}
int main(int argc, char *argv[]) {
registerSignalHandlers();
//rest of the code goes here
return 0;
}
我在带有debian:stretch 图像的docker 容器中运行我的应用程序,tini 作为 PID 1(直接使用它而不是通过bash)。当我在我的设备(MacBook Pro)上运行容器时,一切正常,没有任何问题。我试图在我的代码中导致分段错误SIGSEGV 异常来测试处理程序触发器,在我的设备上,它工作正常,但是一旦我在服务器(CentOS 7)上运行相同的容器,处理程序就根本不工作。
我所说的根本不工作的意思是我的应用程序永远不会收到信号。我尝试从容器kill -15 PID_OF_APPLICATION 内部手动发送信号,并且处理程序工作得很好,但如果发送kill -11 PID_OF_APPLICATION 处理程序不起作用并且不知道为什么!
我尝试使用strace 检查我的代码是否引发了信号,我能够看到SIGSEGV 引发了。
另外,我尝试运行一个脚本来运行我的应用程序和trap 它接收到的信号。在脚本中接收到信号,但处理程序也没有被触发
我不确定我是否遗漏了与 docker 容器配置相关的内容(我正在使用 docker-compose),但我认为我做的一切都是正确的,因为我的设备上有同一个 docker-compose 文件正在启动容器,它可以正常工作。
容器内的应用程序发出的信号是否也通过 PID 1 处理? tini 就我而言。
非常感谢任何帮助
更新
如果我将入口点设置为 sleep infinity 并使用 docker exec -it container_id bash 进入 docker 容器,然后手动启动我的应用程序作为前台进程,处理程序可以正常工作
【问题讨论】:
-
Docker 捕捉到一些信号。根据个人经验,我知道它对键盘中断 (Ctrl-c) 起作用,但我不知道其他信号。我的猜测是必须有一些 Docker 配置来进行信号处理?
-
我浏览的所有资源都在谈论从主机向容器发送信号,但我没有发现任何对从容器内部发出的信号有用的东西。我试图覆盖默认停止信号,但也没有任何效果@HumphreyWinnebago