2016-10-28 2 views
0

Есть ли способ отправить сигнал процессу (в Linux), что приводит к завершению процесса после прохождения «atexit-функций» (в этом случае : void shutdownEngines())? Использование «pkill name» не работает.Завершение работы программы с вызовами функций atexit (Linux)

#include <cstdlib> 
void shutdownEngines() {/*is not executed by "pkill name"*/} 
int main() { 
    atexit(shutdownEngines); 
    while(true) 
     doStuff(); 
} 

Использование: В настоящее время я программирую робота. Каждый раз, когда я хочу его протестировать, я запустил программу и завершил ее с помощью «pkill name», но «shutdownEngines» не вызывается, и робот продолжает двигаться, падая со стола и т. Д.

Я знаю, что могу сделайте «pkill name; ./shutdownEngines.sh», но в моем случае это будет очень плохой стиль (номера контактов gpio, подключенных к движкам, определены в файле заголовка основной программы (исходный код основной программы не принадлежит роботу, но на моем компьютере). Убедившись, что всегда есть программа «shutdownEngines.sh»/скрипт с правильными штырей на каждом роботе будет очень сложным.

Update

Следующий код работает отлично:

#include <iostream> 
#include <csignal> 
#include <cstdlib> 
void signalHandler(__attribute__((unused)) const int signum) { 
    exit(EXIT_FAILURE); 
} 
void driverEpilog() { 
    std::cout << "shutting down engines..."; 
    //drv255(0,0); 
} 
int main() { 
    signal(SIGTERM, signalHandler); 
    atexit(driverEpilog); 
    while(true) 
     system("sleep 1"); 
} 
+1

Это поможет вам, если вы привыкнете читать страницу руководства. –

+0

Когда вы отправляете сигнал процессу (по умолчанию), процесс умирает без прохождения 'exit()', поэтому процедуры, зарегистрированные с помощью 'atexit() 'не вызываются. Вам придется написать обработчик сигнала, который проходит через 'exit()' - который не поддерживается стандартом C, и даже POSIX официально не разрешает его (см. [Как избежать использования 'printf()' в обработчик сигнала] (http://stackoverflow.com/questions/16891019/)) - главным образом потому, что нет контроля над функциями, выполняемыми в обработчиках 'atexit'. –

+0

http://stackoverflow.com/questions/7376228/linux-c-catching-kill-signal-for-graceful-termination – Cyclonecode

ответ

4

от человека страницы atexit:

Функции зарегистрированной с помощью atexit() (и on_exit (3)) не называется , если процесс завершается ненормально, потому что доставки сигнала .

atexit вызывается, когда ваша основная процедура возвращается или когда вы вызываете exit, а не по сигналу.

Когда вы звоните pkill, вы отправляете сигнал SIGTERM. Обработайте этот сигнал с помощью signal или sigaction вместо этого (определите обработчики на SIGTERM, SIGINT, SIGFPE, ...), чтобы остановить двигатели перед выходом из вашей программы.

Пример снят с GNU C library documentation:

void 
termination_handler (int signum) 
{ 
    struct temp_file *p; 

    for (p = temp_file_list; p; p = p->next) 
    unlink (p->name); // don't delete files, stop your engines instead :) 
} 

int 
main (void) 
{ 
    … 
    struct sigaction new_action, old_action; 

    /* Set up the structure to specify the new action. */ 
    new_action.sa_handler = termination_handler; 
    sigemptyset (&new_action.sa_mask); 
    new_action.sa_flags = 0; 

    sigaction (SIGINT, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
    sigaction (SIGINT, &new_action, NULL); 
    sigaction (SIGHUP, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
    sigaction (SIGHUP, &new_action, NULL); 
    sigaction (SIGTERM, NULL, &old_action); 
    if (old_action.sa_handler != SIG_IGN) 
    sigaction (SIGTERM, &new_action, NULL); 
    … 
} 

(конечно, обработчик не может справиться с «сигнал» SIGKILL, который говорит ОС удалить процесс из списка активных процессов, без предварительного уведомления!)

Смежные вопросы