2013-08-27 16 views
5

Czy istnieje sposób na skorzystanie z połączenia systemowego wait() z limitem czasu, poza wykorzystaniem pętli zajętości oczekującej lub zajętości?Czy istnieje wersja wywołania systemowego wait(), który ustawia limit czasu?

Mam proces nadrzędny, który sam w sobie jest fork, a exec jest plikiem wykonywalnym podrzędnym. Następnie czeka na dziecko do końca, pobiera jego wyjście za pomocą wszelkich odpowiednich środków i wykonuje dalsze przetwarzanie. Jeśli proces nie zakończy się w określonym czasie, zakłada, że ​​jego wykonanie zostało przekroczone, i robi coś innego. Niestety, wykrywanie przekroczenia limitu czasu jest konieczne z uwagi na charakter problemu.

+2

Pamiętaj, jeśli zapytamy, dlaczego potrzebujesz czegoś takiego? (w przypadku, gdy istnieją rozwiązania alternatywne) –

+0

Możliwy duplikat [odpowiednik Waitpid z limitem czasu?] (http://stackoverflow.com/questions/282176/waitpid-equivalent-with-timeout) –

Odpowiedz

4

Nie ma połączenia oczekującego, które powoduje przekroczenie limitu czasu.

Zamiast tego można zainstalować procedurę obsługi sygnału, która ustawia flagę dla SIGCHLD, i użyć select() do wprowadzenia limitu czasu. select() zostanie przerwany przez sygnał. potrzebna jest

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 
} 

Więcej logika, jeśli masz inny sygnał trzeba obchodzić się jak dobrze chociaż

+0

Jeśli już instalujesz pętlę odpytywania, możesz równie dobrze skonfigurować signalfd, aby złapał sygnał. –

3

Można użyć opcji waitpid wraz z opcją WNOHANG i uśpienia.

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

Ale to będzie aktywny sen. Jednak nie widzę innego sposobu korzystania z funkcji typu wait.

+0

"oprócz używania zajętego oczekiwania lub zajętości- Śpiąca pętla "Uważam to za nieskuteczną ostatnią deskę ratunku. – Alex

+0

@Alex Wydaje się, że nie przeczytałem dokładnie tego pytania. Jednak nie widzę sposobu, aby znaleźć się poza tym – hek2mgl

3

na Linuksie, można również rozwiązać ten problem za pomocą signalfd. signalfd zasadniczo przyjmuje zestaw sygnałów i tworzy fd, które można odczytać; każdy odczytany blok odpowiada sygnałowi, który wystrzelił. (Należy zablokować te sygnały z sigprocmask tak, że nie są one rzeczywiście wysłany.)

Zaletą signalfd jest to, że można korzystać z fd z select, poll lub epoll, z których wszystkie pozwalają na limity czasu, a wszystkie które pozwalają również czekać na inne rzeczy.

Jedna uwaga: jeśli ten sam sygnał zostanie uruchomiony dwukrotnie, zanim zostanie odczytany odpowiedni struct signalfd_siginfo, otrzymasz tylko jedno wskazanie. Tak więc, gdy pojawi się wskazanie SIGCHLD, musisz wielokrotnie powtarzać waitpid(-1, &status, &WNOHANG), aż zwróci wartość -1.

W FreeBSD można uzyskać ten sam efekt bardziej bezpośrednio za pomocą kqueue i kevent typu EVFILT_PROC. (Możesz także utworzyć zdarzenie SIGCHLD, ale EVFILT_PROC pozwala określić zdarzenia przez pid dziecięcy zamiast globalnie dla wszystkich dzieci.) Powinno to również działać w systemie Mac OS X, ale nigdy go nie wypróbowałem.

Powiązane problemy