Bernd Brodesser
* Eilert Brinkmann schrieb am 29.Mai.2000:
Das ist offensichtlich richtig, obwohl in man 3 sleep von nanosleep nicht die Rede ist, dort wird nur alarm(2) erwähnt. Dient wohl nur zur verwirrung, denn alarm wird definitiv nicht aufgerufen.
In `man 3 sleep' steht nur, daß sleep() unter Verwendung von SIGALARM implementiert sein *könnte* (unter Solaris ist es das laut Dokumentation auch), und das man es deshalb nicht mit Aufrufen von alarm() vermischen sollte: sleep() may be implemented using SIGALRM; mixing calls to alarm() and sleep() is a bad idea. Das scheint vor allem ein Tip für portable Programmierung zu sein, heißt aber noch nicht, daß die Implementierung in einer bestimmten Bibliothek unbedingt so aussehen muß.
Nun bekommt der Prozeß ein anderes Signal und wird fortgesetzt. Da der nanosleep-Aufruf durch ein Signal unterbrochen wurde, kehrt er sofort mit einer Fehlermeldung (errno == EINTR) zurück, bevor die Zeit abgelaufen ist.
Wenn ich es richtig verstanden habe, so hat aber nanosleep gerade dafür den zweiten Eintrag. Damit sollte es doch zu bewerkstelligen sein, daß nanosleep neu gestartet wird.
Ja, allerdings scheint die Implementierung von sleep() das nicht zu tun. Es ist auch fraglich, ob das wirklich sinnvoll wäre. Schließlich würde das bedeuten, die gesamte Zeitverzögerung durch den sleep()-Aufruf um die Zeit zu verlängern, die der Prozeß gestoppt war, und das könnte fast genauso unerwünscht sein wie die Verkürzung. Im Falle einer vorzeitigen Unterbrechung liefert sleep() immerhin die Anzahl der noch nicht geschlafenen Sekunden zurück, damit ließe sich vielleicht was anfangen.
Würde es sleep bzw. nanosleep genauso machen, käme ihre Zeit durcheinander. Denn die Zeit, wo der Prozeß angehalten ist, würde nicht mitgezählt. Dafür hat nanosleep den zweiten Eintrag. Aber irgendwie klappt das mit sleep nicht. Oder habe ich es doch nicht richtig verstanden.
Im allgemeinen ist sleep() ganz bequem, aber wenn es wirklich drauf ankommt, sollte man wohl besser per Hand mit nanosleep() arbeiten, auf die Rückgabewerte achten und vielleicht auch noch mit gettimeofday() die Systemzeit im Auge behalten und Zeitdifferenzen überprüfen, falls es auf die geschlafene Realzeit ankommt.
-> tail -5 bla rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask ist offensichtlich ein Systemaufruf, aber man rt_sigprocmask sagt nur:
Kein Manual-Eintrag für rt_sigprocmask vorhanden
Die rt_sig...()-Funktionen sind für den Umgang mit Realtime-Signalen vorgesehen, ansonsten dürften sie ihrer Bedeutung nach in etwa den "herkömmlichen" Funktionen entsprechen. Trotzdem ärgerlich, daß es keine Doku dazu gibt :-( Ich vermute mal, daß diese Funktionen hier intern von der sleep(3)-Implementierung verwendet werden. Das Ändern der Behandlung von SIGCHLD ist wahrscheinlich eine allgemeine Vorkehrung und unabhängig davon, ob der konkrete Prozeß irgendwelche Kinder hat.
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 nanosleep({1000, 0}, 0xbffff07c) = -1 EINTR (Interrupted system call) ^^^^^^^^^^ Was will uns das sagen? Offensichtlich eine Adresse, aber worauf?
Auf ein struct timespec mit der noch nicht geschlafenen Zeit. Fragt sich, warum strace hier nicht wie sonst den Inhalt der Struktur ausgibt.
Ich habe mal strace -f -o bla sleep 1000 gemacht mit anschließendem im Hintergrundschicken:
[...]
4736 nanosleep({1000, 0},
4736 --- SIGCONT (Fortgesetzt) --- 4736 <... nanosleep resumed> 0xbffff5ec) = -1 ENOSYS (Function not implemented) Hier also ist der SIGCONT zu finden. Aber warum nur hier, und ein Kind habe ich auch nicht gefunden, überall nur die gleiche Prozeßnummer, das ganze strace lang.
Gut zu wissen, daß man bei Verwendung von -o auch das Signal zu sehen bekommt (ging mit einfacher Umleitung nicht). Zum fehlenden Kind siehe oben.
Das SIGCONT kommt also im nanosleep, was auch nicht weiter überrascht. nanosleep gibt ein ENOSYS zurück, womit sleep nichts anfangen kann und daher abbricht. Das heißt, sleep bekommt es gar nicht mehr zu Gesicht, oder? Sonst würde da doch ein _exit stehen. Aber ohne -f gibt strace auch ein _exit aus. Was denn jetzt?
Anscheinend verhält sich strace mit der Option -f etwas seltsam. Ohne bekommt man auch korrekt ein EINTR zu sehen, und dieses ENOSYS dürfte eigentlich nicht sein.
Irgendwie bin ich jetzt noch verwirrter.
Bis auf die seltsamen Variationen in der strace-Ausgabe sollte jetzt das meiste geklärt sein, oder?
Einfach die Zeit, die der Prozeß angehalten war zu übergehen, wäre sicher auch nicht richtig, aber so ist es sicher falsch.
ACK (siehe oben). Eilert -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eilert Brinkmann -- Universitaet Bremen -- FB 3, Informatik eilert@informatik.uni-bremen.de - eilert@tzi.org - eilert@linuxfreak.com http://www.informatik.uni-bremen.de/~eilert/ --------------------------------------------------------------------- To unsubscribe, e-mail: suse-linux-unsubscribe@suse.com For additional commands, e-mail: suse-linux-help@suse.com