2013-08-27 9 views
5

Esiste un modo per utilizzare la chiamata di sistema wait() con un timeout, oltre a utilizzare un ciclo di attesa occupato o di occupato occupato?Esiste una versione della chiamata di sistema wait() che imposta un timeout?

Ho un processo padre che è lo stesso fork s e exec s eseguibile figlio. Attende quindi che il bambino finisca, acquisisca il suo risultato con qualsiasi mezzo appropriato e esegua un'ulteriore elaborazione. Se il processo non termina entro un certo periodo di tempo, si presume che la sua esecuzione sia scaduta e faccia qualcos'altro. Sfortunatamente, questo rilevamento del timeout è necessario data la natura del problema.

+2

Ti dispiace se ti chiediamo perché hai bisogno di una cosa del genere? (nel caso ci siano alternative) –

+0

Possibile duplicato di [Waitpid equivalent with timeout?] (http://stackoverflow.com/questions/282176/waitpid-equivalent-with-timeout) –

risposta

4

Non c'è una chiamata di attesa che richiede un timeout.

È possibile invece installare un gestore di segnale che imposta un flag per SIGCHLD e utilizzare select() per implementare un timeout. select() verrà interrotto da un segnale.

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 
} 

più logica è necessario se si dispone di altro segnale è necessario gestire come bene però

+0

Se stai già installando un ciclo di polling, potresti anche impostare un signalfd per catturare il segnale. –

3

È possibile utilizzare waitpid insieme all'opzione WNOHANG e una sospensione.

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

Ma questo sarà un sonno attivo. Tuttavia non vedo altro modo utilizzando il tipo di funzioni wait.

+0

"oltre a utilizzare un busy-waiting o busy- anello per dormire "Considero questa una inelegante ultima risorsa. – Alex

+0

@Alex Sembra che non abbia letto abbastanza attentamente la domanda. Ma comunque non vedo un modo accanto a questo – hek2mgl

3

su Linux, è anche possibile risolvere questo problema utilizzando signalfd. signalfd essenzialmente prende una serie di segnali e crea un file che puoi leggere; ogni blocco letto corrisponde a un segnale che ha sparato. (Si dovrebbe bloccare questi segnali con sigprocmask in modo che non vengano effettivamente inviati.)

Il vantaggio di signalfd è che è possibile utilizzare il fd con select, poll o epoll, i quali consentono di timeout, e tutti che ti permettono di aspettare anche altre cose.

Una nota: se lo stesso segnale si attiva due volte prima che venga letto il corrispondente struct signalfd_siginfo, riceverai solo una singola indicazione. Pertanto, quando si ottiene un'indicazione SIGCHLD, è necessario eseguire il comando waitpid(-1, &status, &WNOHANG) finché non restituisce -1.

Su FreeBSD, è possibile ottenere lo stesso effetto piuttosto direttamente utilizzando kqueue e un kevent di tipo EVFILT_PROC. (Puoi anche kqueue un evento SIGCHLD, ma EVFILT_PROC ti consente di specificare gli eventi in base al pid figlio anziché a livello globale per tutti i bambini.) Questo dovrebbe funzionare anche su Mac OS X, ma non l'ho mai provato.