select durch Signal unterbrochen "Interrupted system call"
-
Hallo,
Folgende Situation:
Für einen internen Scheduler nutze ich das SIGALRM. Das Signal wird jede Sekunde generiert und soll durch das Scheduler Objekt verarbeitet werden.
In einem anderen Thread der Applikation geschieht gleichzeitig ein select() Befehl. Dieser wird wohl, so vermute ich, durch das SIGALRM Signal unterbrochen. Die Fehlermeldung
select failed: Interrupted system call
weist zumindest darauf hin.Meine Frage: Kann der entsprechende Select Befehl vor der Signal-Verarbeitung geschützt werden? Bzw. kann der gesamte Thread die Signale des Vater Threads ignorieren?
Wenn ich nun den Select-Abschnitt mit
signal (SIGALRM, SIG_IGN);
schütze, ist der andere Thread davon auch betroffen?
Was ist eurer Meinung nach, in einem solchen Fall Best-Practice?
-
Am Einfachsten ist das select() neu zu starten wenn eine Unterbrechung kam. Du kannst dir aber auch mal sigaction() ansehen.
-
Am einfachsten ist es, auf Signale zu verzichten. Wenn Du einen Thread hast, der nur auf das SIGALARM wartet, dann mach dort doch einfach einen sleep (oder nsleep).
-
Signale können trotzdem kommen (nur nicht mehr so regelmäßig). Die Unterbrechnungsbehandlung ist also immer sinnvoll. Die Verwendung von SigAlarm dagegen extrem selten. Wenn man schon pthreads verwendet und man einen relativ genaues Intervall braucht kann man auch die pthread_cond_timedwait Bedingung benutzen.
-
Alle Signale zu ignorieren kommt wirklich nicht in Frage, da ich ja andere Signale sauber bearbeiten will.
Pthread bietet mit der Funktion
pthread_sigmask()
die Möglichkeit jedem Thread eine eigene Signal mask zu geben. Damit sollte es doch möglich sein, dem Select-Thread eine leere Signal-Maske zu setze, damit nur dieser Thread sämtliche Signale ignoriert.Aber auch wenn ich dem entsprechenden Thread eine eigenes Signal-Set gebe, bekomme ich die Meldung das der Select unterbrochen wurde.
sigset_t EmptySigSet={}; if ( pthread_sigmask(SIG_SETMASK ,&EmptySigSet, NULL) !=0){ // Fehlerbehandlung } select(...)
Wende ich die Funktion falsch an? Stimmt die Initialisierung des leeren SignalSet? Die Funktion pthread_sigmask() gibt keinen Fehler zurück.
Ich zweifle, dass es Sinn macht, das Select()-Statement immer wieder neu zu starten, da sehr viel mehr SIGAlRM auftreten (4 Hz).
-
Wenn du kein Timeout bei select() nutzt, gibt es kein Grund der gegen einen Neustart spricht. In Linux gibt es für diesen Fall (Neustart bei Unterbrechung) sogar extra ein Makro. Als Stichwort gibt es noch SA_RESTART.
-
Ich Dussel habe die
pthread_sigmask()
-Funktion völlig falsch angewendet.(Siehe mein vor-gängiger Post)// Ignore SIGALRM sigset_t EmptySigSet={}; sigemptyset(&EmptySigSet); sigaddset(&EmptySigSet, SIGALRM); if ( pthread_sigmask(SIG_BLOCK ,&EmptySigSet, NULL) !=0){ // went wrong }
Dieses Code-Fragment blockiert die Verarbeitung des SIGALRM-Signals für diesen Thread nun richtig.
Und tatsächlich: Der andere, zuständige Scheduler-Thread verarbeitet weiterhin brav die SIGALRM's ohne das der Select-Thread unterbrochen wird.Damit bleibt der Select-Thread von den Signalen unbehelligt und ich kann mir weiter Lösungen wie etwa Select-Restart sparen.
Wieder viel gelernt. Danke für eure Antworten.
-
Wenn noch andere Signale auftreten können kannste es dir nicht sparen.