C shell打印输出无限制,无需停在gets()

时间:2013-03-07 19:29:44

标签: shell unix operating-system

我正在尝试使用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;
}

1 个答案:

答案 0 :(得分:0)

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

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

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