Переопределить Ctrl-C - PullRequest
       2

Переопределить Ctrl-C

12 голосов
/ 02 октября 2011

Я должен переопределить сигнал Ctrl C и использовать его для печати сообщения.Не предполагается завершать программу.

Пока что происходит, что при нажатии Ctrl C она печатает сообщение, но завершает программу.

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

Есть ли способ, который я должен добавить, или мне нужно куда-то переместить установщики сигнала?

Это мой код:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>  
#include <sys/types.h>
#include <signal.h> 
#include "Input.h"
#include "CircleBuff.h"

//void handler_function(int signal_id);

void catch_int(int sig_num){

    //reset the signal handler again to catch_int, for next time
    signal(SIGINT, catch_int);
    //print message
    printf("Print History");
    fflush(stdout);
}

void printHistory(CircleBuff hist){
    cout << "Complete History:\n" << endl;
    hist.print();
    cout << endl;
}

int main(int argc, char** argv){

  struct sigaction signal_action;                /* define table */
  signal_action.sa_handler = catch_int;   /* insert handler function */
  signal_action.sa_flags = 0;                    /* init the flags field */
  sigemptyset( &signal_action.sa_mask );     /* are no masked interrupts */
  sigaction( SIGINT, &signal_action, NULL ); /* install the signal_action */

  do{


  //My code: where the value report will be assigned within.

  } while(report != 1)

}

Ответы [ 2 ]

10 голосов
/ 02 октября 2011

Ух, путь слишком много кода, чтобы его просеять. Однако, если вы используете стандартную библиотеку C, вы должны получить желаемое поведение. Вот версия C ++:

#include <iostream>
#include <csignal>

sig_atomic_t sigflag = 0;

void sighandler(int s)
{
  // std::cerr << "Caught signal " << s << ".\n"; // this is undefined behaviour
  sigflag = 1; // something like that
}

int main()
{
  std::signal(SIGINT, sighandler);

  // ... your program here ...

  // example: baby's first loop (Ctrl-D to end)
  char c;
  while (std::cin >> c)
  {
    if (sigflag != 0) { std::cerr << "Signal!\n"; sigflag = 0; }
  }
}

Это поймает Ctrl-C (что поднимает SIGINT), и обработчик сигнала не заменяется, поэтому он будет срабатывать каждый раз, и никто не завершает программу.

Обратите внимание, что обработчики сигналов наследуются fork() ed дочерними элементами.

Функция Posix sigaction() позволяет регистрировать обработчики «одного выстрела», которые заменяются стандартным обработчиком после их вызова один раз. Хотя это более продвинутое и специфичное для Posix.

Редактировать: Как указывает @Dietrich, вы никогда не должны выполнять никакой реальной работы внутри обработчика сигнала. Скорее, вы должны установить флаг (я привел пример) и проверить этот флаг внутри вашего цикла (и напечатать сообщение там). Я тоже исправлю пример для этого.

0 голосов
/ 02 октября 2011

Считаете ли вы, что внутри вашего цикла while может быть прерываемая функция, завершающаяся с ошибкой EINTR.Вы могли бы быть в состоянии исправить это, используя:

sa.sa_flags = SA_RESTART;

Или просто проверив errno для этого и зацикливаясь.Вы уверены, что программа не заканчивается до конца?Попробуйте поместить оператор печати в конце main.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...