2008-10-08 2 views
5

Прежде чем начать, я хочу пояснить, что это не инструмент командной строки, а приложение, которое принимает команды через собственный интерфейс командной строки.Как обрабатывать сигнал ctrl-break в интерфейсе командной строки

Редактировать: Я должен извиниться перед своим объяснением, прежде чем, по-видимому, я не очень хорошо объяснил это. Еще один раз ...

Я создаю приложение командной строки, которое принимает команды от пользователя. У меня есть настройка обработчика сигналов, чтобы поймать сигналы, которые затем устанавливают флаг, который мне нужно прекратить. Проблема, с которой я столкнулась, - это все функции консоли, которые я могу найти, блокирующие, что означает, что я не могу обнаружить, что мне нужно выйти из цикла обработки консоли до тех пор, пока пользователь не нажмет клавишу (или не войдет, в зависимости от функции).

Есть ли какой-то стандартный способ, который я могу выполнять как неблокирующее взаимодействие с консолью, так и элегантный способ структурирования программы, так что если я просто закончу из сигнальной нити, все будет обработано и выпущено правильно (пожалуйста не понимайте этого, я знаю, как это можно сделать, используя блокировку и освобождение ресурсов от сигнальной нити, но это может стать беспорядочным, поэтому я бы предпочел избежать этого)

Надеюсь, это объяснение имеет смысл ...

ответ

6

На * Никс, вы можете использовать функцию signal зарегистрировать обработчик сигнала:


#include <signal.h> 

void signal_handler(int sig) 
{ 
    // Handle the signal 
} 

int main(void) 
{ 
    // Register the signal handler for the SIGINT signal (Ctrl+C) 
    signal(SIGINT, signal_handler); 
    ... 
} 

Теперь всякий раз, когда кто-то попадает Ctrl + C, ваш обработчик сигналов будет вызван.

0

В системе на основе nix вам может не понадобиться обработчик сигналов для этого. Можно указать, что вы хотите игнорировать SIGINT позвонить

int main(void) 
{ 
    // Register to ignore the SIGINT signal (Ctrl+C) 
    signal(SIGINT, SIG_IGN); 

    while(1) 
    { 
    retval = my_blocking_io_func(); 
    if(retval == -1 && errno == EINTR) 
    { 
     // do whatever you want to do in case of interrupt 
    } 
    } 
} 

Важный способ, которым это работает, чтобы признать, что не блокирующие функции делают дело прерывается. Обычно вы понимаете, что функция блокировки завершилась неудачно (например, read()) и повторно активирует функцию. Если бы это было какое-то другое значение, вы бы предприняли соответствующее действие, связанное с ошибкой.

8

OK - это работает для меня на Windows & переносится - обратите внимание на #ifdef SIGBREAK - это не стандартный сигнал.

#include <csignal> 
#include <iostream> 
#include <ostream> 
#include <string> 
using namespace std; 

namespace 
{ 
    volatile sig_atomic_t quit; 

    void signal_handler(int sig) 
    { 
     signal(sig, signal_handler); 
     quit = 1; 
    } 
} 

int main() 
{ 
    signal(SIGINT, signal_handler); 
    signal(SIGTERM, signal_handler); 
#ifdef SIGBREAK 
    signal(SIGBREAK, signal_handler); 
#endif 
    /* etc */ 

    while (!quit) 
    { 
     string s; 
     cin >> s; 
     cout << s << endl; 
    } 
    cout << "quit = " << quit << endl; 
} 
+1

Примечание: на Windows, нажмите на кнопку закрытия поднимет значи код `SIGBREAK` (ctrl- ломать) – 56ka 2014-08-12 13:35:43

0

Лучше * Никс решение, которое является поточно является использование pthread_sigmask() вместо сигнала().
Например, это то, как вы синьор SIGINT, SIGTERM и SIGPIPE в текущем потоке и будущем породил темы:

sigset_t waitset; 
sigemptyset(&waitset); 
sigaddset(&waitset, SIGINT); 
sigaddset(&waitset, SIGTERM); 
sigaddset(&waitset, SIGPIPE); 
pthread_sigmask(SIG_BLOCK, &waitset, NULL); 
Смежные вопросы