LINUX.ORG.RU

Непонятки с waitpid


0

0

Есть вот такой код:

pid_t newprocess = fork();
if (newprocess < 0){
    perror ("fork");
    exitValue = -1;
} else if (newprocess) {
    // child
    if(waitpid(newprocess,&status,0) < 0) {
        perror ("waitpid");
        exitValue = -1;
    } else if(WIFEXITED(status)) {
        exitValue = WEXITSTATUS(status);
    } else if(WIFSIGNALED(status)) {
        exitValue = 0;
    } else {
        if (WIFSTOPPED(status))
            printf ("exec failed: program stopped by signal %d\n", WSTOPSIG(status));
        else 
            printf ("exec failed: ???\n");
                
        exitValue = -1;
    }
} else {
    char *shell[] = {"/bin/sh", "-c", cmdline, NULL};
       
    environ = envp;
       
    execvp(shell[0], shell);

    exitValue = errno;
    showSystemErrorMessage (exitValue);
    _exit(exitValue);
}

Код этот вызывается из Java-вского native метода.
Почти всегда все работает хорошо, но иногда waitpid падает с ошибкой
ECHILD, однако программа (это происходит всегда при вызове /bin/cp)
отрабатывает нормально, т.е. файлы оказываются успешно скопироваными.
В чем тут может быть дело? Что-то я не соображу. Единственное, что
приходит в голову, глядя в man waitpid - может быть, игнорируется
SIGCHLD. А что еще может привести к такому поведению?

Спасибо.

anonymous

> может быть, игнорируется SIGCHLD.

или он не SIG_IGN, но установлен обработчик, который делает
wait(). тогда, если child process успеет завершиться прежде,
чем parent в вашем коде вызовет waitpid(), вы и получите
ECHILD.

блокируйте SIGCHLD перед fork():

sigset_t sig;
sigemptyset(&sig);
sigaddset(&sig, SIGCHLD);
sigprocmask(SIG_BLOCK, &sig, 0);

после waitpid() sigprocmask(SIG_UNBLOCK).

если программа multithreaded, вместо этого можно выставить
обтработчик SIGCHLD в SIG_DFL, сохранив старый, потом
восстановить. потому что SIG_BLOCK заблокирует только
для текущего потока. это, однако, не очень хорошо: потеряется
информация об exit() других child процессов за это время, если
таковый случатся.

idle ★★★★★
()
Ответ на: комментарий от idle

> потеряется информация об exit() других child процессов

неправильно выразился, они станут zombie.

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.