Почему поведение программы может зависеть от того, в каком порядке заканчиваются ее потомки?

Я запускаю несколько программ, используя fork(), а затем execve() из третьей программы. Все, для чего предназначались эти программы, сделано, но в конце третья программа не возвращается... т.е. командная строка не появляется.

Если я использую команду wait() в вызывающей программе, то программы execve возвращаются только в том случае, если порядок операторов ожидания соответствует порядку окончания программ execve. Почему это могло быть?

Вот упрощенный код:

int main()
{
   int child1,child2,status;
   char*newargv1[] = {./xyz",NULL};
   char *newargv2[] = {./abc",NULL};

   if((child1 = fork())==0)
      execve(newargv1[0],newargv1,NULL);
   if((child2 = fork())==0)
      execve(newargv2[0],newargv2,NULL);

    while(wait(&status) != child1);
    while(wait(&status) != child2);
  }

Он отлично работает, если ребенок1 заканчивает первым. ./xyz и ./abc имеют простую обработку и управление доходит до конца.


person Lipika Deka    schedule 18.06.2011    source источник
comment
Используйте waitpid с неблокирующим флагом и опросом вместо ожидания.   -  person Keith    schedule 18.06.2011
comment
Или waitpid с блокировкой. Если второй процесс завершится первым, вам не придется ждать его очень долго.   -  person luser droog    schedule 18.06.2011
comment
@Pavel, спасибо за редактирование, но название вопроса было не таким, каким я его планировал.   -  person Lipika Deka    schedule 18.06.2011


Ответы (2)


while(wait(&status) != child1);
while(wait(&status) != child2);

В этом коде вы будете ждать, пока child1 завершится, но если child2 завершится первым, вы получите статус и сбросите его. Затем, когда child1 закончится - вы перейдете к следующему циклу, но тогда вы никогда не получите статус для child2, потому что вы его уже отбросили.

Вместо этого сохраните массив дочерних элементов и зацикливайте wait до тех пор, пока вы не получите статус для каждого из членов массива в одном цикле while, тогда вы не попадете в тупик.

person littleadv    schedule 18.06.2011

Это звучит как правильное поведение для того, что вы описываете. wait() блокирует до тех пор, пока не произойдет то, чего он ждет. Если программа wait выполняет несколько действий подряд, ей придется ждать несколько действий подряд. Похоже, вы используете waitpid() вместо wait(). Если вы используете настоящий wait(), вам просто нужно вызвать его столько раз, сколько нужно ждать дочерних элементов.

Если вам все равно, какой порядок, сделайте так, чтобы программа не зависела от какого-либо конкретного порядка.

person luser droog    schedule 18.06.2011
comment
Нет, я использую wait(). Я имел в виду, что порядок ожидания должен соответствовать порядку возврата, иначе он не работает. При такой реализации нельзя контролировать порядок возврата. - person Lipika Deka; 18.06.2011
comment
Я говорю, что это кажется ненужным. Похоже, вы не используете возвращаемое значение pid_t ни для чего, кроме этой проверки, которая является причиной вашей проблемы. Поэтому не делайте этого. Просто дважды вызовите wait и игнорируйте возвращаемое значение. ...И избавьтесь от петель! Просто сделай: (void)wait(&status); (void)wait(&status); - person luser droog; 18.06.2011