2013-08-27 2 views
5

Есть ли способ использовать системный вызов wait() с таймаутом, кроме того, используя занятый или занятый спальный цикл?Есть ли версия системного вызова wait(), которая устанавливает тайм-аут?

У меня есть родительский процесс, который сам fork и exec s дочерний исполняемый файл. Затем он ждет, пока ребенок закончит, захватывает свой результат любыми средствами, подходящими и выполняет дальнейшую обработку. Если процесс не завершается в течение определенного периода времени, он предполагает, что его выполнение истекло, и делает что-то еще. К сожалению, это определение таймаута необходимо, учитывая характер проблемы.

+2

Помните, если мы спросим, ​​зачем вам нужно такое? (в случае, если есть альтернативы) –

+0

Возможный дубликат [эквивалент Waitpid с таймаутом?] (http://stackoverflow.com/questions/282176/waitpid-equivalent-with-timeout) –

ответ

4

Существует не вызов ожидания, требующий тайм-аута.

Вместо этого вы можете установить обработчик сигнала, который устанавливает флаг для SIGCHLD, и используйте select() для реализации тайм-аута. select() будет прерван сигналом.

static volatile int punt; 
static void sig_handler(int sig) 
{ 
    punt = 1; 
} 

... 

struct timeval timeout = {10,0}; 
int rc; 

signal(SIGCHLD, sig_handler); 

fork/exec stuff 
//select will get interrupted by a signal 

rc = select(0, NULL,NULL,NULL, &tv); 
if (rc == 0) { 
// timed out 
} else if (punt) { 
    //child terminated 
} 

Больше логики требуется, если у вас есть другой сигнал, вам нужно работать, как хорошо, хотя

+0

Если вы уже устанавливаете цикл опроса, вы можете также настроить signalfd, чтобы поймать сигнал. –

3

Вы можете использовать waitpid вместе с опцией WNOHANG и сон.

while(waitpid(pid, &status, WNOHANG) == 0) { 
    sleep(1); 
} 

Но это будет активный сон. Однако я не вижу другого способа использования функций типа wait.

+0

«помимо использования оживленного или занятого- спальная петля «Я считаю это недействующим последним средством. – Alex

+0

@Alex Кажется, я недостаточно внимательно прочитал вопрос. Но, однако, я не вижу пути рядом с этим – hek2mgl

3

В Linux, вы можете решить эту проблему с помощью signalfd. signalfd по существу принимает набор сигналов и создает fd, который вы можете прочитать; каждый прочитанный вами блок соответствует сигналу, который был запущен. (Вы должны блокировать эти сигналы с sigprocmask так, чтобы они не отсылаются.)

Преимущество signalfd является то, что вы можете использовать ФД с select, poll или epoll, все из которых позволяют для тайм-аута, и все которые позволяют вам ждать и других вещей.

Одно примечание: если один и тот же сигнал срабатывает дважды перед чтением соответствующего struct signalfd_siginfo, вы получите только одно указание. Поэтому, когда вы получаете индикацию SIGCHLD, вам нужно до waitpid(-1, &status, &WNOHANG) до тех пор, пока она не вернет -1.

На FreeBSD вы можете добиться такого же эффекта, скорее, с помощью kqueue и kevent типа EVFILT_PROC. (Вы также можете зарегистрировать событие SIGCHLD, но EVFILT_PROC позволяет указывать события дочерним pid, а не глобально для всех детей.) Это также должно работать на Mac OS X, но я никогда не пробовал.

Смежные вопросы