You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言信号功能异常:偶数信号处理函数未执行求助

Root Cause of the Even Signal Handler Failure

The primary issue here is an uninitialized variable in the first child process that prevents it from setting up the SIGUSR1 handler. Let's break down what's happening:

1. Uninitialized pid2 in Child 1

When the parent forks pid1 (child 1), the child 1 process skips the pid2 = fork() line because pid1 is 0 in the child context. This means pid2 in child 1 is uninitialized (holds a random garbage value). The condition !pid1 && pid2 for child 1 will almost certainly evaluate to false (since pid2 could be 0 or an invalid value), so child 1 never installs the SIGUSR1 handler.

When the parent sends SIGUSR1 to child 1, the default signal action (termination) is triggered instead of your custom handler. That's why you see no output for even numbers—child 1 dies immediately after the first even signal is sent.

2. Additional Issues & Fixes

Beyond the main bug, there are several other problems in the code that need addressing for reliability and correctness:

a. Poor Process Structure

Your original code puts parent and child logic in the same infinite loop, leading to redundant signal handler setup and uninitialized variables. Instead, handle child processes immediately after forking.

b. Unclosed Pipe File Descriptors

Each process should close unused pipe ends to avoid unexpected behavior (like read() hanging waiting for EOF that never arrives).

c. Non-Async-Signal-Safe Functions in Handlers

printf() and sleep() are not async-signal-safe, which means using them in a signal handler can cause undefined behavior. Replace printf() with write() (a safe alternative) and avoid sleep() in handlers.

d. Unseeded Random Number Generator

rand() will generate the same sequence of numbers every run unless you seed it with srand(time(NULL)).

Fixed Code Implementation

Here's the corrected code with all these fixes applied:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>

pid_t pid1, pid2;
int fd[4]; 

// Async-signal-safe handler for even numbers (SIGUSR1)
void handler_one() {
    int ric1;
    read(fd[0], &ric1, sizeof(int));
    
    char buf[100];
    ssize_t len = snprintf(buf, sizeof(buf), "I'm the first child process...the even received number is...%d\n", ric1);
    write(STDOUT_FILENO, buf, len);
}

// Async-signal-safe handler for odd numbers (SIGUSR2)
void handler_two() {
    int ric2;
    read(fd[2], &ric2, sizeof(int));
    
    char buf[100];
    ssize_t len = snprintf(buf, sizeof(buf), "I'm the second child process...the odd received number is...%d\n", ric2);
    write(STDOUT_FILENO, buf, len);
}

int main() {
    // Initialize pipes
    if (pipe(fd) == -1 || pipe(fd + 2) == -1) {
        perror("pipe failed");
        exit(1);
    }

    // Fork first child
    pid1 = fork();
    if (pid1 == -1) {
        perror("fork pid1 failed");
        exit(1);
    } else if (pid1 == 0) {
        // Child 1 setup: handle SIGUSR1, close unused pipes
        signal(SIGUSR1, handler_one);
        close(fd[1]); // Close write end of first pipe
        close(fd[2]); // Close read end of second pipe
        close(fd[3]); // Close write end of second pipe
        
        // Wait indefinitely for signals
        while (1) {
            pause();
        }
    }

    // Fork second child (only parent reaches here)
    pid2 = fork();
    if (pid2 == -1) {
        perror("fork pid2 failed");
        exit(1);
    } else if (pid2 == 0) {
        // Child 2 setup: handle SIGUSR2, close unused pipes
        signal(SIGUSR2, handler_two);
        close(fd[0]); // Close read end of first pipe
        close(fd[1]); // Close write end of first pipe
        close(fd[3]); // Close write end of second pipe
        
        // Wait indefinitely for signals
        while (1) {
            pause();
        }
    }

    // Parent setup: close unused pipes, seed random generator
    close(fd[0]); // Close read end of first pipe
    close(fd[2]); // Close read end of second pipe
    srand(time(NULL));

    // Parent loop: generate random numbers and send to children
    while (1) {
        printf("I'm the parent and I'm gonna send a random number\n");
        int r = rand() % 10 + 1;
        
        if (r % 2 == 0) {
            write(fd[1], &r, sizeof(int));
            kill(pid1, SIGUSR1);
        } else {
            write(fd[3], &r, sizeof(int));
            kill(pid2, SIGUSR2);
        }
        
        sleep(1);
    }

    return 0;
}

Key Changes Explained

  • Process Structure: Each child is handled immediately after forking, eliminating uninitialized variables and redundant handler setup.
  • Pipe Cleanup: Unused pipe ends are closed in each process to prevent resource leaks and unexpected behavior.
  • Safe Signal Handling: Replaced printf() with write() to avoid undefined behavior in signal handlers.
  • Seeded Randomness: srand(time(NULL)) ensures different random sequences on each run.
  • Proper Waiting: Children use pause() to wait for signals efficiently instead of looping unnecessarily.

This should resolve the issue with the even signal handler not responding, and make the code more robust overall.

内容的提问来源于stack exchange,提问作者Hackasim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:55:48