почему WIFSIGNALED имеет значение false, если я завершаю процесс с помощью SIGPIPE +, почему код выхода 256? - PullRequest
0 голосов
/ 16 апреля 2019

Программа состоит из 2 частей (меня попросили использовать трубу): A. менеджер - который создает процессы, которые помогут ему рассчитать, сколько экземпляров определенного символа находится в файле. B. Count - Подсчитывает, сколько экземпляров в файле и возвращает канал менеджеру. Более того, в каждой программе я менял поведение SIGPIPE и менял желаемое поведение.

в менеджере.c:

for(i = 0; i < len_sym; i++){
        ...
        if (pipe(pipe_fds + (2 * i)) == -1) {
            perror("ERROR : Failed creating pipe");
            exit(EXIT_FAILURE);
        }
        if ((curr_child = fork()) == 0){ //son
            dup2(pipe_fds[2*i + 1], STDOUT_FILENO);
            close(pipe_fds[2*i + 1]);
            close(pipe_fds[2*i + 0]);
            execvp(child_args[0], child_args);
        }
        else { //parent
            if (curr_child == -1){
                exit(EXIT_FAILURE);
            }
            close(pipe_fds[2*i + 1]); // close writerfd
            child_pids[i] = curr_child;
            printf("%d son created with pid %d\n", i + 1, child_pids[i]);
            // if (i == 1) {
            //     kill(curr_child, SIGPIPE);
            // }
        }
    }

    for(i = 0; i < len_sym; i++){
        curr_child = waitpid(child_pids[i], &exit_code, 0);
        printf("exit code %d\n", exit_code);
        printf("child pid %d\n", curr_child);

        if (curr_child == -1 || 256 == exit_code) {
            exit(EXIT_FAILURE);
        }

        if (WIFEXITED(exit_code)) {
            int bytes_read;
            while ((bytes_read = read(pipe_fds[i*2 + 0], buff, BUFF_SIZE)) > 0) {
                buff[bytes_read] = '\0';
                printf("%s", buff);
            }
            if (bytes_read == -1) {
                perror("ERROR : Failed reading from fifo");
                close(pipe_fds[i*2 + 0]);
                exit(EXIT_FAILURE);
            }
            close(pipe_fds[i*2 + 0]);
            child_pids[i] = 0;
        }
    }

обработка SIGPIPE в manager.c


void my_signal_handler(int signum) {
    switch (signum) {
        case SIGPIPE:
            printf("SIGPIPE for Manager process %d. Leaving\n", getpid());
            for (int i = 0; i < len_sym; i++) {
                if ((child_pids != NULL) && child_pids[i]) {
                    kill(child_pids[i], SIGTERM);
                }
            }
            exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

void register_signal_handlin() {
    struct sigaction new_action;
    memset(&new_action, 0, sizeof(new_action));
    new_action.sa_handler = my_signal_handler;
    if (0 != sigaction(SIGPIPE, &new_action, NULL)) {
        exit(EXIT_FAILURE);
    }
}

в счет.с:

for (j = 0; j < file_length; j++){
        if (*temp++ == c){
            counter++;
        }
    }
    sleep(10);
    if (argc > 4){
        sprintf(buff, "Process %d finishes. Symbol %c. Instances %d.\n", getpid(), c, counter);
        int buff_len = strlen(buff);
        int bytes_written;
        while ((bytes_written = write(writerfd, p, buff_len)) > 0) {
            p += bytes_written;
            buff_len -= bytes_written;
        }
        if (bytes_written == -1) {
            perror("PROCESS ERROR : Failed writing to fifo");
            close(writerfd);
            return EXIT_FAILURE;
        }
        close(writerfd);
    }

обработка SIGPIPE в count.c

void my_signal_handler(int signum) {
    switch (signum) {
        case SIGPIPE:
            printf("SIGPIPE for process %d. Symbol %c. Counter %d.\n", getpid(), c, counter); 
            exit(EXIT_FAILURE);
        case SIGTERM:
            exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}


void register_signal_handling() {
    struct sigaction new_action;
    memset(&new_action, 0, sizeof(new_action));
    new_action.sa_handler = my_signal_handler;

    if (0 != sigaction(SIGPIPE, &new_action, NULL)) {
        exit(EXIT_FAILURE);
    }
    if (0 != sigaction(SIGTERM, &new_action, NULL)) {
        exit(EXIT_FAILURE);
    }
}

Таким образом, на самом деле я запускаю программу менеджера и одновременно открываю новый терминал и отправляет kill -13 определенному процессу.

проблемы:

  1. В диспетчере я получаю код выхода 256. Почему?

  2. Флаг WIFSIGNALED не включается, хотя я отправил сигнал процессу.

  3. Возвращение из функции waitpid не -1, а номер процесса, который я отправил kill -13 со второго терминала.

  4. Я пытался отправить kill одному из детей от менеджера, и по какой-то причине он активировал обработчик сигнала менеджера, а не обработчик сигнала ребенка.

Я нахожусь в процессе изучения ОС, поэтому буду рад любой помощи.

...