1

我正在尝试使用 SIGCHLD 处理程序,但由于某种原因,它会打印我无限发出的命令。如果我删除结构行为它工作正常。

任何人都可以看看它,我无法理解问题所在。提前致谢!!

    /* Simplest dead child cleanup in a SIGCHLD handler. Prevent zombie processes
   but dont actually do anything with the information that a child died. */

#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

typedef char *string;

/* SIGCHLD handler. */
static void sigchld_hdl (int sig)
{
    /* Wait for all dead processes.
     * We use a non-blocking call to be sure this signal handler will not
     * block if a child was cleaned up in another part of the program. */
    while (waitpid(-1, NULL, WNOHANG) > 0) {
    }
}

int main (int argc, char *argv[])
{
    struct sigaction act;
    int i;
    int nbytes = 100;
    char my_string[nbytes];
    string arg_list[5];
    char *str;
    memset (&act, 0, sizeof(act));
    act.sa_handler = sigchld_hdl;

    if (sigaction(SIGCHLD, &act, 0)) {
        perror ("sigaction");
        return 1;
    }

while(1){

    printf("myshell>> ");
    gets(my_string);
    str=strtok(my_string," \n");
    arg_list[0]=str;
    i =1;
    while ( (str=strtok (NULL," \n")) != NULL){
            arg_list[i]= str;
            i++;
        }
    if (i==1)
        arg_list[i]=NULL;
    else
        arg_list[i+1]=NULL;

     pid_t child_pid;
    child_pid=fork();
    if (child_pid == (pid_t)-1){
        printf("ERROR OCCURED");
        exit(0);
        }

    if(child_pid!=0){
        printf("this is the parent process id is %d\n", (int) getpid());
        printf("the child's process ID is %d\n",(int)child_pid);

    }
    else{
        printf("this is the child process, with id %d\n", (int) getpid());
        execvp(arg_list[0],arg_list);
        printf("this should not print - ERROR occured");
        abort();
    }

    }
    return 0;
}
4

1 回答 1

0

我没有运行你的代码,只是假设:

SIGCHLD正在到达并打断fgets(我只是假装你没有使用gets)。 fgets在实际读取任何数据之前返回,my_string包含它在前一个循环中具有的标记化列表,你再次分叉,输入fgets,它在读取任何数据之前被中断,并无限期地重复。

换句话说,检查 的返回值fgets。如果它为 NULL 并且已设置errno为 EINTR,则再次调用 fgets。(或设置act.sa_flags = SA_RESTART。)

于 2013-03-07T20:45:05.640 回答