简体   繁体   English

`waitpid()'总是返回-1

[英]`waitpid()' always returns -1

I'm executing the code below and the call to waitpid() always returns -1 , thus the code bellow ends with an infinite loop. 我正在执行以下代码,对waitpid()的调用始终返回-1 ,因此下面的代码以无限循环结尾。 The call works if I replace WNOHANG with 0 . 如果我将WNOHANG替换为0则该呼叫有效。

void execute(cmdLine* pCmdLine) {
    int status = 0;
    pid_t pid = fork();
    if(pid == 0) {
         if(execvp(pCmdLine->arguments[0], pCmdLine->arguments) == -1) {
             if(strcmp(pCmdLine->arguments[0], "cd") != 0) {
               perror("execute failed\n");
             }
        _exit(1);
        }
    } else {
        if(pCmdLine->blocking == 1) {
            waitpid(pid, &status, 0);
        }
            while(waitpid(pid, &status, WNOHANG) == -1) {
             printf("still -1\n");
            }
         }     
    }
}

Well, you have misunderstood the workings of the wait system call. 好吧,您误解了wait系统调用的工作方式。

As with malloc/free , you can only successfully waitpid() only once per fork() ed process... so the while loop is never necessary if you are going to wait for the exit code of the child, you have to call it only once. malloc/free ,每个fork()进程只能成功等待一次waitpid() ,因此,如果您要等待子代的退出代码,则while循环永远不需要,您必须调用它只有一次。 Wait will only return -1 in your case because of two reasons: 在您的情况下,等待只会返回-1 ,这有两个原因:

  • fork() didn't succeed, so you are waiting for an invalid pid . fork()没有成功,因此您正在等待无效的pid Indeed, you should be calling wait() for pid == -1 , which is invalid. 确实,您应该为pid == -1调用wait() ,这是无效的。 In case you wait() and there's no process to be waited for (in case the pid variable has a positive number, but of an already wait() ed subprocess, you also get -1 ), you get an error from any of the wait() family of system calls. 如果您使用wait()并且没有等待的过程(如果pid变量的值为正数,但是已经使用过wait()子过程,您也会得到-1 ),那么您会从任何wait()系列系统调用。 The mission of zombie processes in UN*X systems is just this, to ensure that a wait() for an already finished child is still valid and the calling process gets the exit code signalled by the child on exit() . UN * X系统中的僵尸进程的任务就是这样,以确保对已完成的子进程的wait()仍然有效,并且调用进程获取该子进程在exit()上发出的退出代码。
  • You expressely say you are not going to wait for the process to finish. 您明确地说您不会等待该过程完成。 It should be clear that if you are not going to wait for the process to terminate, this is what you are doing with the WNOHANG parameter, then the child process can be still running (which is your case) and had not yet done an exit() syscall. 应该清楚的是,如果您不打算等待进程终止,那么这就是使用WNOHANG参数执行的操作,那么子进程可能仍在运行(这是您的情况)并且尚未完成exit() syscall。 You only want the exit code in case the child process has already finished. 如果子进程已经完成,则只需要退出代码。 If this is the case, then you had better to write: 如果是这种情况,那么您最好编写:

     while(waitpid(pid, &status, WNOHANG) == -1 && errno == EAGAIN) do_whatever_you_want_because_you_decided_not_to_wait(); 

    The wait system call has no way to tell you that the &status variable has not been filled with the exit code of the child process than signalling an error, and in that case, it always sets errno to EAGAIN . wait系统调用没有办法告诉您&status变量还没errno通知errno来填充子进程的退出代码,在这种情况下,始终将errnoEAGAIN

    but, from my point of view, if you have nothing to do in the meanwhile, then you had better not to use WNOHANG . 但是,从我的角度来看,如果与此同时无事可做,那么最好不要使用WNOHANG That will save cpu cycles and a lot of heat energy thrown to the environment. 这样可以节省CPU周期并节省大量散发到环境中的热能。

Here 这里

 while(waitpid(pid,&status,WNOHANG)==-1) { }

when if there is no more child process exists then waitpid returns -1 and it makes while(true) always and that cause infinite loop. 如果不再存在子进程,则waitpid返回-1 ,它始终使while(true)并导致无限循环。

From the manual page of waitpid() . waitpid()的手册页开始。

waitpid(): on success, returns the process ID of the child whose state has changed ; waitpid():成功时,返回状态已更改的子进程的ID if WNOHANG was specified and one or more child(ren) specified by pid exist, but have not yet changed state, then 0 is returned. 如果指定了WNOHANG ,并且存在由pid指定的一个或多个孩子,但尚未更改状态,则返回0 On error, -1 is returned. 出错时,返回-1

That means, when there are no more child to wait for, it returns -1 . 这意味着,当没有其他孩子等待时,它返回-1 So either make it like 所以要么让它像

if() { /* child process. can be multiple */
} 
else { /* parent process */
    while(waitpid(pid,&status,WNOHANG) != -1) { /* when there is no more child process exists then it terminate */ 
    }
}

or 要么

if() { /* child process. can be multiple */
} 
else { /* parent process */
  while(waitpid(pid,&status,WNOHANG) == -1);  /* dummy while ..when there is no more child process exists then it terminate */ 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM