简体   繁体   English

C子进程未收到SIGINT信号

[英]C child process doesn't receive SIGINT signal

I have some problem with processing signals. 我在处理信号时遇到问题。 I'm creating a simple web server, and I don't understand why my initial process successfully catches and handles SIGINT signals, but the child processes it fork() s seem not to do so. 我正在创建一个简单的Web服务器,但我不明白为什么我的初始进程成功捕获并处理了SIGINT信号,但是子进程对其fork()似乎不这样做。 Here is my code: 这是我的代码:

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include "thpool.h"
#include <pthread.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/sendfile.h>

int asc;
threadpool thpool;

void sighand(int sig) { //function handler
    if (sig == SIGINT) {
        printf("ctr-c recived\n");
        go = 0;
        thpool_destroy(thpool);
        shutdown(asc, 2);
        close(asc);
        int a = 1;
        setsockopt(asc, SOL_SOCKET, SO_REUSEADDR, &a, sizeof(int));
        exit(2);
}

void fun(void *client_socket) { 
    int sock = *(int*)client_socket;
    char buffer[1024]; 
    int n = read(sock, buffer, BUFFERSIZE);
    printf("%s\n", buffer);
}

int main() {
    int pid;

    if (signal(SIGINT, sighand) == SIG_ERR) //signal function
        perror("signal failed\n);
    pid = fork();
    if (pid == 0) { //new process
        int port = 8666, client_socket;
        struct sockaddr_in server, client;
        pthread_mutex_t M;
        pthread_mutex_init(&M,NULL);
        int parent = getppid();
        value = kill(parent, SIGTERM);  //kill the parent
        if (value == 0)
            printf("dead parent\n");
        else
            perror("errore");
        thpool = thpool_init(2); 

        //creazione socket
        asc = socket(AF_INET, SOCK_STREAM, 0); //new socket
        printf("\nsocket aperto\n");
        bzero((char *)&server, sizeof(server));

        //inizializzazione
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = htons(port);
        bind(asc, (struct sockaddr *)&server, sizeof(struct sockaddr_in)
        printf("bind effettuata\n");
        listen(asc, 40) 
        printf("listen effettuata\n");
        printf("in attesa di connessione....\n");
        client_leng = sizeof(client);
        while (go) {
            if ((client_socket = accept(asc, (struct sockaddr *)&client, &client_leng)) < 0) {
                perror("accept fallita");
                exit(0);
            } else {
                pthread_mutex_lock(&M);
                printf("accept effettuata\n");
                thpool_add_work(thpool, (void *)fun, (void *)&client_socket);
                puts("handler assigned\n");
                pthread_mutex_unlock(&M);
            }
        }
    }

TL;DR : you are signaling a different process than you think you are. TL; DR :您所发出的信号与您认为的信号不同。

You mention in comments that you are trying to deliver a SIGINT to your process by typing CTRL-C on the keyboard. 您在注释中提到,您试图通过在键盘上键入CTRL-C向过程提供SIGINT That's fine when you want to kill the foreground process group of the terminal then owning the keyboard. 当您想杀死终端的前台进程组然后拥有键盘时,这很好。 Supposing that you launch your program from a shell window and it does nothing to put itself in the background, the initial process will indeed be in the foreground process group, and if you never fork() then nothing else you do do changes that until the process terminates. 假设您从外壳程序窗口启动程序,并且没有做任何事情使其自身进入后台,则初始进程确实将在前台进程组中,并且如果您从不使用fork()那么您所做的任何更改都不会更改,直到进程终止。 Typing CTRL-C in that terminal will therefore deliver a SIGINT to that process. 因此,在该终端中键入CTRL-C将为该进程传递一个SIGINT

HOWEVER, when the initial process dies, the shell that launched it puts itself back in the foreground. 但是,当初始进程终止时,启动它的外壳会将其放回前台。 You can check this by typing commands to it. 您可以通过键入命令来检查它。 Moreover, in the case where the initial process successfully fork() sa child, the child and its process group move into the background when the when the shell puts itself in the foreground. 此外,在初始进程成功fork()一个child的情况下,当shell将自己置于前台时,child及其进程组将移入后台。 At that point, any CTRL-C you type goes to the shell (which ignores it), not to the child of your webserver process. 那时,您键入的任何CTRL-C都将转到外壳程序 (忽略它),而不是Web服务器进程的子进程。

You can send a SIGINT to a process running in the background or without a controlling terminal via the kill command, for example 您可以通过kill命令将SIGINT发送到在后台运行或没有控制终端的进程,例如

kill -INT 12345

If you use that method to deliver a SIGINT to the child process in your fork ing case, you will see that the process's registered signal handler catches and handles the signal exactly as it should. 如果在fork情况下使用该方法将SIGINT传递给子进程,则将看到该进程的已注册信号处理程序将按其应有的方式捕获并处理该信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM