0

我在尝试处理信号时遇到问题...

我有一个多线程应用程序,它接收一个中断我正在使用的库中的系统调用的信号。经过一番研究,我发现如果一个信号没有被处理,它会被发送到应用程序中的一个随机线程。我已经从我正在使用的库中确认他们没有在他们的应用程序中使用任何信号。我也不是。这是我的主要驱动程序类:

void sig_handler(int signum)
{
    cout << "Signal Handle: " << signum << endl;
    signal(signum, SIG_IGN);
}


class Driver
{
    public:
        Driver();
        void LaunchLog();
        void logonListen();
};

Driver::Driver()
{
    pthread_t logThread;
    pthread_create(&logThread, NULL, LaunchLogThread, (void*) this);
    pthread_detach(logThread);

    pthread_t listenThread;
    pthread_create(&listenThread, NULL, LaunchListenThread, (void*)this);
    pthread_detach(listenThread);

    bool running = true;

    while(running)
    {
        //Simple loop to resemble a menu for the console
    }
}

void Driver::logonListen()
{
    char buffer[256];

    int logonPort = BASEPORT;
    int sockfd;
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t clilen;

    //initialize socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0){
        perror("Error opening socket");
        exit(1);
    }
    bzero((char*)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(logonPort);

    //bind socket to our address
    if(bind(sockfd,(struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
    {
        perror("Error on bind");
        exit(1);
    }

    clilen = sizeof(struct sockaddr_in);

    int n;
    int nextUser = 2;
    char reply[32];

    while(1)
    {
        //Wait for incoming connection on a socket
    }
}

void Driver::LaunchLog()
{
    Logger::Instance()->WriteToFile();
}

void* LaunchListenThread(void* ptr)
{
    Driver* driver = (Driver*) ptr;
    driver->logonListen();
}

int main()
{
    signal (SIGHUP, sig_handler);
    signal (SIGINT, sig_handler);
    signal (SIGQUIT, sig_handler);
    signal (SIGILL, sig_handler);
    signal (SIGTRAP, sig_handler);
    signal (SIGFPE, sig_handler);
    signal (SIGKILL, sig_handler);
    signal (SIGUSR1, sig_handler);
    signal (SIGSEGV, sig_handler);
    signal (SIGUSR2, sig_handler);
    signal (SIGPIPE, sig_handler);
    signal (SIGALRM, sig_handler);
    signal (SIGTERM, sig_handler);
    signal (SIGCHLD, sig_handler);
    signal (SIGCONT, sig_handler);
    signal (SIGSTOP, sig_handler);
    signal (SIGTSTP, sig_handler);
    signal (SIGTTIN, sig_handler);
    signal (SIGTTOU, sig_handler);
    signal (SIGABRT, sig_handler);
    Driver driver;
    return 0;
}

我无法处理这些信号。中断的系统调用不断增加,我的信号处理程序永远不会被使用。即使我在控制台中按 CTRL+C,程序也会以中断而不是处理 SIGINT 结束。我是否错误地安装了处理程序?

有没有办法处理所有信号并在它们出现时忽略它们?

谢谢

4

2 回答 2

1

几件事。首先,您应该检查signal(). 如果安装信号处理程序时出现问题,它可以返回 SIG_ERR(至少在某些情况下可能存在问题,因为其中一些信号是不可捕获的)。其次,在信号处理程序中使用stdio/iostream函数可能是有问题的,因为它们是异步的(相对于程序中可能使用相同设施的其他东西)性质。第三,在您的信号处理程序中,即使第一次调用它,您也会将该信号设置为被忽略,因此该信号的任何后续实例(假设它是可捕获的)都将被忽略。如果您想一开始就忽略它们,则无需编写处理程序,只需signal(SIG<whatever>, SIG_IGN)main().

于 2012-09-24T15:31:53.260 回答
1

您想使用带有 SA_RESTART 标志的 sigaction(2) 来忽略信号并确保系统调用重新启动而不是中断:

struct sigaction sa;
sa.sa_hanlder = SIG_IGN;
sa.sa_flags = SA_RESTART;

sigaction(SIGALRM, &sa);
sigaction(SIGPIPE, &sa);
/* repeat for all the signals you want to ignore */

请注意,您可能不想忽略诸如 SIGINT 之类的内容,因为您将无法停止使用 ctrl-C 进行编程。同样,忽略 SIGSEGV 可能会导致您的程序在包含错误时挂起,而不是退出。

编辑

您关于您和图书馆都没有使用任何信号的描述并不完全正确 - 信号来自某个地方,并且可能只是您没有意识到您正在做的事情是在幕后使用信号. 如果您在任何地方使用任何警报或计时器,这些都涉及信号。如果您的 sig_handler 确实没有被调用,则意味着其他人(您的库?)正在安装信号处理程序来替换它。

如果您仍然无法确定信号来自何处,您可以在调试器下运行,并启用调试器的信号调试功能(如果需要)。这至少应该告诉您哪些信号正在发生,以及它们在哪里发生。

一般来说,对于任何系统调用,您应该始终检查错误,如果您意外看到错误 EINTR,您可能应该循环并重做系统调用。

于 2012-09-24T16:01:03.460 回答