C дочерний процесс не получает сигнал SIGINT - PullRequest
0 голосов
/ 29 января 2019

У меня проблемы с обработкой сигналов.Я создаю простой веб-сервер, и я не понимаю, почему мой первоначальный процесс успешно перехватывает и обрабатывает сигналы SIGINT, но дочерний процесс обрабатывает его fork(), кажется, не делает этого.Вот мой код:

#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);
            }
        }
    }

1 Ответ

0 голосов
/ 30 января 2019

TL; DR : вы сигнализируете о другом процессе, отличном от того, который вы думаете.

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

ОДНАКО, когда начальный процесс умирает, оболочка, запустившая его, возвращается на передний план.Вы можете проверить это, набрав команды к нему.Более того, в случае, когда начальный процесс успешно fork() является дочерним, дочерний процесс и его группа процессов переходят в фоновый режим, когда оболочка ставит себя на передний план. В этот момент любой введенный вами CTRL-C отправляется в оболочку (которая его игнорирует), а не в дочерний процесс вашего веб-сервера.

Вы можете отправить SIGINT напроцесс выполняется в фоновом режиме или без управляющего терминала с помощью команды kill, например

kill -INT 12345

Если вы используете этот метод для доставки SIGINT дочернему процессу в вашем случае fork ing, вы увидите, что зарегистрированный обработчик сигнала процесса перехватывает и обрабатывает сигнал именно так, как и должен.

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