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

创建可fork子进程的C守护进程时出现僵尸进程问题求助

Fixing Zombie Child Processes in Your Daemon

Hey there! Let's break down why your child processes are turning into zombies after setting up the daemon, and how to fix it.

What's Causing the Zombies?

Looking at your ps -ajx output and code, the main culprit is likely incorrect error handling in your wait loop combined with potential unhandled failures in execv. Here's the breakdown:

  • When wait() gets interrupted by a signal (like EINTR), your current code treats it as a child exit, decrements num_of_children, and eventually exits the loop. This leaves un-reaped child processes that become zombies.
  • If execv fails (e.g., wrong path, missing execute permissions), the child process exits immediately—but if your wait loop isn't working right, it won't get reaped.

Step-by-Step Fixes

1. Fix the wait Loop Error Handling

Update your wait loop to properly handle interrupts and errors, so it only decrements the child count when a valid child exit is detected:

int status;
pid_t pid;
while(num_of_children > 0) {
    pid = wait(&status);
    if (pid == -1) {
        if (errno == EINTR) {
            // Wait was interrupted by a signal—keep waiting
            continue;
        } else if (errno == ECHILD) {
            // No more children to wait for, exit loop
            syslog(LOG_INFO, "No remaining child processes to monitor");
            break;
        } else {
            // Log other wait errors and exit
            syslog(LOG_ERR, "Wait failed: %s", strerror(errno));
            break;
        }
    }
    // Log valid child exit
    syslog(LOG_INFO, "Child %d exited with status 0x%x", pid, status);
    num_of_children--;
}

This ensures you don't incorrectly count interrupts as child exits, and properly handle all edge cases for wait().

2. Add Error Handling for execv

If execv fails (returns instead of replacing the process), your child process will exit immediately—but you should log this failure to debug issues like missing executables:

if(i == 0) {
    syslog(LOG_INFO,"Forked message_server...");
    char * argv_list[] = {"message_queue_server",NULL};
    execv("./assignment_queue_server",argv_list);
    // If we reach here, execv failed
    syslog(LOG_ERR, "Failed to start message_queue_server: %s", strerror(errno));
    exit(EXIT_FAILURE);
}
if(i == 1) {
    syslog(LOG_INFO,"Forked time_check...");
    char * argv_list[] = {"time_check_process",NULL};
    execv("./time_check_process",argv_list);
    // If we reach here, execv failed
    syslog(LOG_ERR, "Failed to start time_check_process: %s", strerror(errno));
    exit(EXIT_FAILURE);
}

Check your system logs (usually /var/log/syslog or /var/log/messages) for these error messages if you still see issues.

Your current daemon setup misses a critical step: a second fork. This ensures your daemon isn't a session leader, preventing it from accidentally opening a terminal. Update your daemonization code:

int main() {
    int pid = fork();
    if(pid > 0) {
        printf("Parent process exiting..\n");
        exit(EXIT_SUCCESS); // No need to sleep—exit immediately
    } else if (pid == 0) {
        printf("First child process..\n");
        if(setsid() < 0) {
            exit(EXIT_FAILURE);
        }
        // Second fork to avoid being session leader
        pid = fork();
        if(pid > 0) {
            exit(EXIT_SUCCESS);
        } else if(pid == 0) {
            umask(0);
            if(chdir("/") < 0) {
                exit(EXIT_FAILURE);
            }
            // Close all file descriptors
            int x;
            for(x = sysconf(_SC_OPEN_MAX); x>=0;x--) {
                close(x);
            }
            openlog("assignment_daemon", LOG_PID|LOG_CONS,LOG_USER);
            syslog(LOG_INFO,"assignment_daemon started...");
            // Rest of your code to fork child processes goes here
        }
    }
    return 0;
}

This follows the standard Unix daemonization best practices.

Additional Troubleshooting Tips

  • Verify that ./assignment_queue_server and ./time_check_process exist and have execute permissions (run ls -l on them).
  • Check your system logs to confirm if the child processes are starting successfully or failing to execute.
  • Remove the sleep(10) in your initial parent process—it's unnecessary and can delay daemon startup.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:52:44