Waitpid работает как будто в неблокирующем режиме - PullRequest
0 голосов
/ 06 февраля 2019

Я играю с системными вызовами в C, и я застрял, пытаясь понять эту программу, которую я создал -

int main(int argc, char* argv[])
{
int a;
char *args[]={"sleep"," 10",NULL}; 

a = fork();
int stat;


if(a==0){
    setpgid(getpid(),getpid());
    printf("%d\n",getpgid(getpid()));
    execvp(args[0],args);}
else
{
    int t2;
    waitpid(-a,&t2,0);
}

printf("Parent pid = %d\n", getpid()); 
printf("Child pid = %d\n", a); 

}

В соответствии с моим пониманием, я установил pgid child в качестве собственного pid.Когда я вызываю waitpid с аргументом -a, я в основном прошу его подождать (заблокировать), пока не завершится какой-либо процесс в pgid = a.Тем не менее, вывод программы не соответствует ожиданиям!Дочерний процесс вообще не пожинается.Как будто waitpid находится в неблокирующем режиме.Вывод:

Parent pid = 11372
Child pid = 11373
11373

(вывод происходит мгновенно, он не ждет 10 секунд!)

РЕДАКТИРОВАТЬ: я добавил printf("Here") и exit(1) ниже execvp и распечатал waitpidвывод, как предлагается в комментариях.Здесь не распечатываются и ждут печатные издания -1

1 Ответ

0 голосов
/ 06 февраля 2019

Проблема в состоянии гонки.После разветвления здесь:

a = fork();

, если дочерний процесс запускается первым, здесь создается группа процессов -a:

if(a==0){
    setpgid(getpid(),getpid());

, а затем родитель ожидает здесь:

waitpid(-a,&t2,0);

, но если родительский запускается первым, группа процессов -a действительно не еще существует, и waitpid() завершается ошибкой с ECHILD.Второй случай, очевидно, происходит в вашей системе.

Вы должны будете найти какой-то способ убедиться, что вызов setpgid() в дочернем процессе выполняется за до вызова waitpid() вродитель.Сложный способ - семафоры, простой (хакерский) способ - короткая задержка, usleep(1) до того, как waitpid(), вероятно, будет достаточно.

...