C - 线程和进程 - 防止僵尸

C - threads and processes - prevent zombies

我正在实现一个接收解析为数组的命令行的函数("./waiter 20 &" 将被解析,函数将接收数组 {"./waiter","20","&"} 例如)。 如果最后一个参数是&,进程应该在后台运行。 为了防止僵尸,我需要使用一个新线程来等待子进程。 附加的代码是我的工作程序,我添加一个等待子进程的新线程的所有努力都失败了。 任何人都可以指导我吗? 附上代码,以及我不成功尝试的一些遗留物。 (函数为process_arglist)

更新:在使用此处建议的方法进行大量尝试后,它仍然失败,我不确定为什么。附上更新的代码。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>

void func(void* ptr) {
    pid_t* mypid = (pid_t*)ptr;
    waitpid(*mypid);
    pthread_detach(pthread_self());
}

int process_arglist(int count, char** arglist){
    int isBackground = 0;
    pid_t  pid;
    int    status;
    char** parsedList;
    if (strcmp(arglist[count-1],"&") == 0) {
        printf("###we are in the & situation\n");
        parsedList = (char**)malloc((count-1)*sizeof(char*));
        if (parsedList == NULL) {
            printf( "Error: malloc failed - %s\n", strerror(errno));
        }
        int i;
        for (i=0;i<count-1;i++){
            parsedList[i] = arglist[i];
        }
        /*printf("parsed list:\n");
        for (i=0;i<count-1;i++) {
            printf(" %d: %s\n", i,parsedList[i]);
        }*/
        if ((pid = fork()) < 0) {     /* fork a child process           */
            printf( "Error: fork failed");
            exit(0);
        } else if (pid == 0) {          /* for the child process:         */
            if (execvp(*parsedList,parsedList) < 0) {     /* execute the command  */
                printf( "Error: execvp failed - %s\n", strerror(errno));
                exit(0);
            }
        } else {
            pthread_t thread;
            pthread_create(&thread, NULL, (void*) &func, (void*) &pid);
        }
    } else {
        if ((pid = fork()) < 0) {     /* fork a child process           */
            printf( "Error: forking child process failed - %s\n", strerror(errno));
            exit(0);
        }
        else if (pid == 0) {          /* for the child process:         */
            if (execvp(*arglist,arglist) < 0) {     /* execute the command  */
                printf( "Error: execvp failed - %s\n", strerror(errno));
                exit(0);
            }
        }
        else {                                  /* for the parent:      */
            while (waitpid(&status) != pid);       /* wait for completion  */
        }
    }
}

首先,从调用 wait 切换到调用 waitpid。否则,如果您有多个线程在等待,它们会窃取彼此的通知。

其次,将对 waitpid 的调用分解为它自己的函数,该函数将要等待的 PID 作为参数。通过 void * 转换它,因为这是用于线程参数的内容。

第三,将对函数的调用更改为对pthread_create的调用,将等待的PID转换为void *以传递给新创建的线程。

最后,让线程分离自身,因为不会有任何东西等待线程终止。