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、前のループで持っていたトークン化されたリストが含まれていると、再び fork し、fgetsデータを読み取る前に中断される に入り、無限に繰り返します。

つまり、 の戻り値を確認しますfgets。NULL でerrnoEINTR に設定されている場合は、fgets を再度呼び出します。(または を設定しact.sa_flags = SA_RESTARTます。)

于 2013-03-07T20:45:05.640 に答える