2013-03-07 1 views
1

Я пытаюсь использовать обработчик SIGCHLD, но по какой-то причине он печатает команду, которую я дал бесконечно. Если я удалю конструкторский акт, он отлично работает.C shell print output бесконечно без остановки при получении()

Может кто-нибудь взглянуть на него, я не могу понять, в чем проблема. Спасибо заранее!

/* 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; 
} 
+2

Никогда не используйте 'gets' !! –

+0

Даже fgets() дает мне ту же проблему !! – trailblazer

+0

Использование 'gets' не является источником симптомов, которые вы видите, но' gets' по своей сути является небезопасным. Он не дает возможности указать, насколько большой целевой массив. Если кто-то запускает вашу программу, более 100 символов в строке, у вас будет переполнение буфера, что приведет к неопределенному (т. Е. Произвольно плохому) поведению. –

ответ

0

Я не запускать свой код, и я просто гипотезу:

SIGCHLD прибывает и прерывание fgets (я просто притворитесь, что вы не использовали gets). fgets возвращает перед фактическим чтением любых данных, my_string содержит токенированный список, который он имел в предыдущем цикле, вы снова используете fork, введите fgets, который прерван перед чтением любых данных и повторяется бесконечно.

Другими словами, проверьте возвращаемое значение fgets. Если он равен NULL и установил errno в EINTR, снова вызовите fgets. (Или установить act.sa_flags = SA_RESTART.)