【问题标题】:handling sigterm in OSx在 OSx 中处理 sigterm
【发布时间】:2015-08-11 12:40:14
【问题描述】:

我在 XCode 6 中构建了控制台 C++ 应用程序,并希望向其添加 SIGTERM 处理程序。有很多例子,但我无法让它们起作用。

#include <csignal>

namespace
{
  volatile std::sig_atomic_t gDone = 0;
}

static void term_handler(int i)
{
  gDone = 1;
}

int main(int argc, const char * argv[])
{
  std::signal(SIGTERM, term_handler);
  while (!gDone);
  return 0;
}

调试器在while 语句处停止,但未调用处理程序。这段代码也有同样的问题

#include <signal.h>

volatile sig_atomic_t gDone = 0;

void term_handler(int i)
{
  gDone = 1;
}

int main(int argc, char* argv[])
{
    struct sigaction sa;
    sigset_t newset;
    sigemptyset(&newset);
    sigaddset(&newset, SIGHUP);
    sigprocmask(SIG_BLOCK, &newset, 0);
    sa.sa_handler = term_handler;
    sigaction(SIGTERM, &sa, 0);

  while(!gDone);  
  return 0;
}

代码有问题吗?在 OSX 中处理信号的正确方法是什么?

【问题讨论】:

  • 你是如何传递信号的?
  • @jxh 使用“kill”。问题是 XCode 中断了循环的执行,实际上显示了执行被 SIGTERM 中断的消息。但处理程序没有被调用。
  • 你能把断点放在return而不是while吗?我不确定while 的突破会给你带来什么。
  • @jxh 我没有放任何断点,XCode 会自动完成。我唯一的断点是在处理程序内

标签: c++ macos signals sigterm


【解决方案1】:

发送信号后,调试器停止,您必须继续到达信号处理程序中的断点。

(lldb) break set -n term_handler
Breakpoint 1: where = a.out`term_handler(int) + 4 at sig.cc:11, address = 0x0000000100000f54
(lldb) run
Process 42532 launched: './a.out' (x86_64)
Process 42532 stopped
* thread #1: tid = 0x18dc39, 0x0000000100000f30 a.out`main(argc=15, argv=0x00007fff5fbffb58) + 32 at sig.cc:17, queue = 'com.apple.main-thread', stop reason = signal SIGTERM
    frame #0: 0x0000000100000f30 a.out`main(argc=15, argv=0x00007fff5fbffb58) + 32 at sig.cc:17
   14   int main(int argc, const char * argv[])
   15   {
   16     std::signal(SIGTERM, term_handler);
-> 17     while (!gDone);
   18     std::puts("done!");
   19     return 0;
   20   }
(lldb) c
Process 42532 resuming
Process 42532 stopped
* thread #1: tid = 0x18dc39, 0x0000000100000f54 a.out`term_handler(i=15) + 4 at sig.cc:11, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000f54 a.out`term_handler(i=15) + 4 at sig.cc:11
   8    
   9    static void term_handler(int i)
   10   {
-> 11     gDone = 1;
   12   }
   13   
   14   int main(int argc, const char * argv[])
(lldb) `

【讨论】:

  • 嗯,我记得我试着继续,但它不会中断,但我会在早上重新检查。
  • 当我按下继续时没有任何反应,应用程序继续运行,并且处理程序内部的断点没有被命中
  • 鉴于我已经演示了我的所有步骤并表明我无法重现您的问题,除了确保您向您的流程发送正确的信号外,我无法为您提供任何进一步的帮助。 kill -SIGTERM whatever-the-process-id-is
  • 好吧,我确定 SIGTERM 信号已发送,因为我尝试了两个 kill 版本,而 XCode 实际上告诉我执行已被 SIGTERM 中断。我还没有检查关于 lldb 的 donjuedo 链接
【解决方案2】:

好的,我现在在家,正在使用我的 Mac。同样,您的代码(特别是第二个示例)已被证明很好。确认是在终端中使用 gcc 和“kill -TERM”完成的。 Source 指的是 SIGTERM,就像正常的一样,但 kill 指的是(在 OS X 上)TERM。您看到的 XCode 暂停是由于 XCode 而不是您的代码。我尝试了两种方式,终端和 XCode。但是,我找不到阻止这种中断的首选项。

只是集中在这里...您问,代码有问题吗?答:不。您问,在 OSX 中处理信号的正确方法是什么?答:你已经这样做了。新问题:如何让 XCode (lldb) 在信号发生时不暂停?答:How to tell LLDB debugger not to handle SIGBUS?

【讨论】:

  • (un?)幸运的是,你是对的,当在调试器会话中,处理程序将无法工作,导致调试器拦截信号。
  • 我认为你仍然可以做到这一点。当我查看“man lldb”时,我看到 lldb 在启动时会读取 3 个文件。我已经使用带有 gdb 的 .gdbinit 文件来设置断点等,从而节省了我手动设置每个调试会话的时间。所以我敢打赌,如果你根据你的 SIGTERM 定制上面提到的 stackoverflow 答案,你可以将该命令放在 lldb 的 init 文件中,XCode 将调用 lldb 并按照你的意愿行事。我想。
【解决方案3】:

您的代码很好。杀死:

kill -SIGTERM 31573

因为

kill -9 31573

31573 是我的进程 ID,没有正常退出。我在您的代码中添加了一个 printf 来告诉我它正在正常退出。

【讨论】:

  • 糟糕。我在 Ubuntu 上完成了这项工作,而不是我刚刚注意到的 OS X。现在我祈祷答案也适合你。
  • kill -9 根本不等同于kill -SIGTERM,这就是为什么您的进程没有以kill -9 正常退出的原因。 SIGKILL,也就是 9 号信号,不可捕获。 SIGTERM 在 Linux 上通常是信号 15 - 不确定 OSX 是否对它们的信号进行了不同的排序......
  • 好的,我现在在家,正在使用我的 Mac。同样,您的代码(特别是第二个示例)已被证明很好。确认是在终端中使用 gcc 和“kill -TERM ”完成的。 Source 指的是 SIGTERM,就像正常的一样,但 kill 指的是(在 OS X 上)TERM。您看到的 XCode 暂停是由于 XCode 而不是您的代码。我尝试了两种方式,终端和 XCode。但是,我找不到阻止这种中断的首选项。
  • 没有新的事情发生。我在 while 运算符说“线程 1:信号 SIGTERM”时得到一个休息,当我按 continue 时,循环永远不会中断,并且处理程序中的断点永远不会被命中
  • 只是集中在这里...您问,代码有问题吗?答:不。您问,在 OSX 中处理信号的正确方法是什么?答:你已经这样做了。新问题:如何让 XCode (lldb) 在信号发生时不暂停?答:stackoverflow.com/questions/11984051/…
猜你喜欢
  • 1970-01-01
  • 2016-11-09
  • 2011-02-27
  • 2021-09-23
  • 2023-04-11
  • 2019-05-20
  • 2016-01-20
  • 2011-08-16
相关资源
最近更新 更多