2015-05-28 2 views
2

У меня есть консольное приложение C++, встроенное в XCode 6, и вы хотите добавить к нему обработчик SIGTERM. Есть много примеров, но я не могу заставить их работать.манипулятор sigterm в OSx

#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?

+1

Как вы доставляете сигнал? – jxh

+0

@jxh, используя «kill». проблема заключается в том, что XCode прерывает выполнение цикла и на самом деле показывает сообщение о том, что исполнение было прервано SIGTERM. но обработчик не вызван. – Sergi0

+0

Можете ли вы поставить точку останова на 'return' вместо' while'? Я не уверен, что ломается «время». – jxh

ответ

1

ОК, я дома сейчас и работает на моем Mac. Опять же, ваш код (второй образец конкретно) оказался просто прекрасным. Подтверждение было сделано в терминале с gcc и «kill -TERM». Источник ссылается на SIGTERM, как обычно, но kill ссылается (на OS X) на TERM. Пауза XCode, которую вы видите, связана с XCode, а не с вашим кодом. Я пробовал это в обоих направлениях, Terminal и XCode. Однако я не мог найти префикса, чтобы препятствовать этому прерыванию.

Просто сосредоточьтесь здесь ... Вы спросили, есть ли проблемы с кодом? Ответ: Нет. Вы спросили: Каков правильный способ обработки сигналов в OSX? Ответ: То, как вы это делаете. Новый вопрос: Как заставить XCode (lldb) не останавливаться при возникновении сигналов? Ответ: How to tell LLDB debugger not to handle SIGBUS?

+0

(un?), К счастью, вы правы, когда в сеансе отладчика обработчик не будет работать, отладчик перехватывает сигналы. – Sergi0

+0

Я думаю, вы все еще можете это сделать. Когда я посмотрел на «man lldb», я увидел упоминание о 3 файлах, которые читал lldb при запуске. Я использовал файлы .gdbinit с gdb для настройки контрольных точек и т. Д., Сохраняя ручную настройку с каждым сеансом отладки. Поэтому я бы поспорил, если вы адаптируете ответ stackoverflow, упомянутый выше, к вашему SIGTERM, вы можете поместить эту команду в файл инициализации для lldb, а XCode вызовет lldb и будет вести себя по вашему желанию. Я думаю. – donjuedo

1

Ваш код в порядке. Убейте с:

kill -SIGTERM 31573 

потому

kill -9 31573 

где 31573 был мой идентификатор процесса, не выйти из грациозно. Я добавил printf к вашему коду, чтобы сказать, что он вышел изящно.

+0

Упс. Я сделал эту работу над Ubuntu, а не с OS X, которую я только что заметил. Теперь я скрещиваю пальцы, что ответ тоже работает для вас. – donjuedo

+0

'kill -9' совсем не эквивалентен' kill -SIGTERM', поэтому ваш процесс не вышел из строя с 'kill -9'. Сигнал SIGKILL', a.k.a. № 9, не может быть использован для поиска. 'SIGTERM' обычно является сигналом 15 на Linux - не уверен, что OSX заказывает свои сигналы по-другому или нет ... – twalberg

+0

Вы правы. Я виню rote (моя собственная память). – donjuedo

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) ` 
+0

ну, я помню, я пытался продолжить и это не сломается, но я перепроверяю по утрам. – Sergi0

+0

ничего не происходит, когда я нажимаю «Продолжить», приложение продолжает работать, а обработчик прерывания внутри не попадает – Sergi0

+0

Видя, как я продемонстрировал все свои шаги и показал, что не могу воспроизвести вашу проблему, я не могу помочь вам дальше, кроме чтобы убедиться, что вы отправляете правильный сигнал в свой процесс. 'kill -SIGTERM any-the-process-id-is' – jxh