2012-09-24 24 views
0

我有麻烦试图处理的信号...无法处理信号,导致interruped系统调用

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

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处理结束。我是否正确安装处理程序?

有没有办法处理所有的信号,并忽略它们,如果它们出现?

谢谢

回答

1

你想用的sigaction(2)用SA_RESTART标志忽略的信号,并确保系统调用就会重新启动,而不是打断:

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可能会导致程序挂起,如果它包含错误而不是退出。

编辑

你的描述,无论是你还是图书馆使用任何信号不颇为不顺 - 信号是从什么地方来了,它可能只是你不知道的情况下,意识到你正在做的事情是在引擎盖下使用信号。如果您在任何地方使用任何闹钟或itimers,那些涉及信号。如果你的sig_handler确实没有被调用,那意味着别人(你的库?)正在安装一个信号处理程序来替换它。

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

一般情况下,任何的系统调用,您应经常检查是否存在错误,如果你看到错误EINTR意外,你应该只循环和重做系统调用。

+0

如果它的多线程处理此问题?我将SIGINT发送到gdb的应用程序中,但它只是结束应用程序而不是进入我的处理程序。我明白你对SIGINT的意思,我试图找到并消除信号的来源,这就是为什么我试图做到这一点。 – Joshua

+0

由于我在Makefile中打开了-pg(分析),信号最终成为了SIGPROF。无法使用调试器来确定它。你能否详细说明我将如何做到这一点? – Joshua

+0

@Joshua,以及gdb,你可以使用'handle all stop'命令让调试器拦截所有的信号并停止程序。然后运行该程序并查看发生了什么信号。在多线程程序中,每个信号只能设置一个信号处理程序,这适用于所有线程。 –

1

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

相关问题