简体   繁体   中英

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. 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.

You mention in comments that you are trying to deliver a SIGINT to your process by typing CTRL-C on the keyboard. 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. Typing CTRL-C in that terminal will therefore deliver a SIGINT to that process.

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. At that point, any CTRL-C you type goes to the shell (which ignores it), not to the child of your webserver process.

You can send a SIGINT to a process running in the background or without a controlling terminal via the kill command, for example

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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