2013-08-27 3 views
5

Gibt es eine Möglichkeit, den Systemaufruf wait() mit einer Zeitüberschreitung zu verwenden und dabei eine busy-waiting- oder busy-slowing-Schleife zu verwenden?Gibt es eine Version des Systemaufrufs wait(), die eine Zeitüberschreitung festlegt?

Ich habe einen Elternprozess, der fork s selbst und exec s ein Kind ausführbar ist. Es wartet dann darauf, dass das Kind fertig ist, ergreift seine Ausgabe mit geeigneten Mitteln und führt eine weitere Verarbeitung durch. Wenn der Prozess nicht innerhalb eines bestimmten Zeitraums abgeschlossen wird, wird davon ausgegangen, dass die Ausführung des Vorgangs abgelaufen ist und etwas anderes tut. Leider ist diese Timeout-Erkennung angesichts der Art des Problems notwendig.

+2

Haben Sie etwas dagegen, wenn wir fragen, warum Sie so etwas brauchen? (falls es Alternativen gibt) –

+0

Mögliches Duplikat von [Waitpid gleichwertig mit Timeout?] (http://stackoverflow.com/questions/282176/waitpid-equivalent-with-timeout) –

Antwort

4

Es gibt keinen Warteaufruf, der eine Zeitüberschreitung erfordert.

Sie können stattdessen einen Signalhandler installieren, der ein Flag für SIGCHLD setzt und mit select() ein Timeout implementiert. select() wird durch ein Signal unterbrochen.

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 
} 

Mehr Logik benötigt, wenn Sie ein anderes Signal haben müssen Sie auch zu handhaben, obwohl

+0

Wenn Sie bereits eine Polling-Schleife installieren, können Sie auch ein Signalfd einrichten, um das Signal zu fangen. –

3

Sie können waitpid zusammen mit der WNOHANG Option und einen Schlaf verwenden.

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

Aber das wird ein aktiver Schlaf sein. Allerdings sehe ich keine andere Möglichkeit die wait Art von Funktionen zu verwenden.

+0

"neben der Verwendung einer busy-waiting oder busy- Schlafschleife "Ich halte dies für einen uneleganten letzten Ausweg. – Alex

+0

@Alex Scheint, dass ich die Frage nicht sorgfältig genug gelesen habe. Aber ich sehe keinen Weg neben dieser – hek2mgl

3

Unter Linux können Sie auch dieses Problem lösen signalfd verwenden. signalfd im Wesentlichen nimmt eine Reihe von Signalen und erstellt eine Fd, die Sie lesen können; Jeder von Ihnen gelesene Block entspricht einem Signal, das ausgelöst wurde. (Sie sollten diese Signale mit sigprocmask blockieren, so dass sie nicht tatsächlich gesendet.)

Der Vorteil signalfd ist, dass Sie die fd mit select verwenden können, poll oder epoll, die alle für die Timeouts erlauben, und alle mit denen Sie auch auf andere Dinge warten können.

Eine Anmerkung: Wenn das gleiche Signal zweimal ausgelöst wird, bevor das entsprechende struct signalfd_siginfo gelesen wird, erhalten Sie nur eine einzige Anzeige. Wenn Sie also eine SIGCHLD-Anzeige erhalten, müssen Sie wiederholt waitpid(-1, &status, &WNOHANG), bis es -1 zurückgibt.

Unter FreeBSD können Sie den gleichen Effekt eher direkt mit kqueue und kevent vom Typ EVFILT_PROC erreichen. (Sie können auch ein SIGCHLD-Ereignis in die Warteschlange stellen, aber in EVFILT_PROC können Sie die Ereignisse nach Kind-PID statt global für alle Kinder angeben.) Dies sollte auch unter Mac OS X funktionieren, aber ich habe es nie ausprobiert.

Verwandte Themen