Asynchrone Benachrichtigungen ohne Signals
-
Hallo,
ich habe folgendes Problem:
Während langer Rechenoperationen soll in der Oberfläche meines Programms ein Runner angezeigt werden. Damit keine Rechenzeit unnötig verschwendet wird (Oberfläche unnötig oft zeichnen), lasse ich mich momentan über SIGALARM in 500ms Abständen benachrichtigen und entscheide daran, ob die Oberfläche neu gezeichnet wird. Soweit so gut, das funktioniert. Das Program ist allerdings, dass diverse Systemcalls (insb. read/write/fcntl) unreproduzierbar unterbrochen werden. Das Problem ist mir völlig klar und die Systemaufrufe müssten eigentlich diese Situation abfragen. Aber - das ist viel zu viel zu machen. Der Rechenkern ist zu groß und die Zeit zu knapp um den komplett zu warten.D.h. ich muss von den Signals weg. Auf Threads zu gehen ist leider keine Lösung, da dass ähnlich große Wartungsarbeiten nach sich zieht.
Am besten wäre eine Lösung, in der man abfragen kann, ob ein Signal aufgetreten ist, ohne dass es zugestellt wird. Leider ist das zumindest so wie ich es herausgefunden habe, nicht möglich (lasse mich gern eines besseren belehren).
Welche Möglichkeiten bleiben mir? Eine Überlegung war, einen Kind-Prozess zu forken, der die Signals bekommt und dem Parent z.B. über eine Pipe signalisiert, dass ein Signal aufgetreten ist. Nicht schön... aber könnte es tun.
Welche Alternativen gibt es noch? Oder wie kann man das anders lösen?
Wichtig wäre - das ganze sollte unter Linux, Tru64 und SunOS funktionieren - sprich eine POSIX oder SystemV-kompatible Lösung wäre stark bevorzugt.
Gruß
-
was mir so spontan einfällt:
1. Du erstellst eine Pipe, forkst ein Child und das Child wartet mit man: select(2) (oder ähnlichem) auf neue Daten zu lesen. Anstelle eines Signals, schiebst du nun einfach ein byte (oder irgend welche Statusinformationen in die pipe).
2. Mittels man: sigaction(2) und SA_RESTART sollte dein Programm nach einem Signal dort weiterlaufen, wo es unterbrochen wurde (also bei einem read/write/fcntl oä)
-
read und write mit SA_RESTART funktioniert leider nur auf "slow devices", also z.B. Terminals, aber leider nicht bei normalen Files. Zumindest für fcntl könnte das wohl Abhilfe schaffen.
Ja das mit der Pipe dachte ich mir auch so in der Art
Danke.
-
Warum kannst du nicht einen Thread, der in einer Schleife nanosleep und danach die Überprüfung ausführt, benutzen?
-
Weil ich oben schon geschrieben habe, dass Threads keine Alternative sind
Liegt einfach daran, dass der Code schon älter ist, statische Variablen enthält etc. pp. Die Umbauarbeiten kommen eben einem Überprüfen jedes fcntl/read/write/close Aufrufs gleich und sind nicht wirklich praktikabel für den Zeitrahmen.
-
7H3 N4C3R schrieb:
Das Program ist allerdings, dass diverse Systemcalls (insb. read/write/fcntl) unreproduzierbar unterbrochen werden. Das Problem ist mir völlig klar und die Systemaufrufe müssten eigentlich diese Situation abfragen. Aber - das ist viel zu viel zu machen.
Ich glaub ich hab das Problem nicht verstanden. Wenn du EINTR bekommst machst du den Syscall nochmal und fertig. Was klappt daran denn nicht?
-
Bashar schrieb:
Ich glaub ich hab das Problem nicht verstanden. Wenn du EINTR bekommst machst du den Syscall nochmal und fertig. Was klappt daran denn nicht?
Das Problem ist den Code zu warten und anzupassen.
Es ist schlichtweg zu viel. Außerdem baut man rein potenziell dabei neue Fehler ein (weil man etwas ändert). Auch wenn man's gut macht, muss man es neu durchtesten. Außerdem ist es für den gegebenen Zeitrahmen zuviel Code (~4000 Zeilen).Deshalb möchte ich auf etwas umbauen, was garnicht erst EINTR auslöst.
-
Ich denke du musst erst alle Signale deaktivieren und dann mit
int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout);
überprüfen ob welche da sind.
Eine Lösung, die EINTR berücksichtigt und Threads benutzt ist sicherlich besser. Vor allem ein Thread der sigwaitinfo oder sigwait benutzt und die Meldungen in eine Pipe schreibt wird wohl kaum mit den globalen Variablen der restlichen Anwendung kollidieren.
-
Aah sowas wie sigtimedwait habe ich gesucht, werd ich mir morgen mal anschauen.
Btw, gegen Multithreading spricht u.a. 25% Performance-Einbruch bei simpler Kompilierung als multithreaded. Dass da irgendwo noch ein Hund begraben liegt mag ja sein, aber - Zeitrahmen. Is nicht, leider
-
7H3 N4C3R schrieb:
Aah sowas wie sigtimedwait habe ich gesucht, werd ich mir morgen mal anschauen.
Btw, gegen Multithreading spricht u.a. 25% Performance-Einbruch bei simpler Kompilierung als multithreaded. Dass da irgendwo noch ein Hund begraben liegt mag ja sein, aber - Zeitrahmen. Is nicht, leider
Wat? Mit -pthread alleine kompilieren bringt 25% weniger?
-
Korrekt. Ziemlich schockierendes/frustrierendes Ergebnis.
Btw, dankeschön
Sieht gut aus mit sigtimedwait