Ich habe da vor ca. einem Jahr ein (für mich) größeres Projekt angefangen. Da ich dafür auf die Mithilfe anderer Programme angewiesen bin, hatte ich eine Klasse P_Exec erstellt, die diese Aufgabe per Fork() und execvp() erledigt. Diese Klasse enthält auch einen Signal-Handler, den ich im wesentlichen von einem früheren Projekt übernommen hatte. Man möchte ja unnötige Zombies vermeiden.
Auszug:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | P_Exec { ... struct sigaction sig_new; struct sigaction sig_old; static void sighandler( int sn ); // our new signal handler int handler_on( void ); int handler_off( void ); static volatile sig_atomic_t pipe_flag; // indicates we got an broken pipe signal int handler_active; ... //----------------------------------------------------------------------------- // Install our own signal handler int P_Exec::handler_on( void ) { int err = 0; pipe_flag = 0; err |= sigemptyset( &sig_new.sa_mask ); sig_new.sa_handler = sighandler; sig_new.sa_flags = 0; err |= sigaction( SIGCHLD, &sig_new, &sig_old ); err |= sigaction( SIGPIPE, &sig_new, 0 ); return err; } // (static) void P_Exec::sighandler( int sn ) { int status; int pid; switch( sn ) { case SIGPIPE: pipe_flag = 1; // broken pipe break; case SIGCHLD: pid = waitpid( -1, &status, WNOHANG ); if( pid > 0 ) // remove from child list pid_rem( pid ); break; } } ... |
Da das bisher immer funktioniert hat, habe ich da nicht weiter drüber nachgedacht.
Aber jetzt kommt ein neues Problem hinzu. Ich hatte kürzlich das Programm um eine einfache Netzwerkfunktionalität erweitert. Da passiert es immer wieder mal, das ich zwar einen Socket erstellen kann, aber anschließend der connect() Aufruf nicht erfolgreich ist. errno steht auf EINTR.
Als Abhilfe wird empfohlen, den Socket zu schließen und es noch einmal zu versuchen. Als Alternative wird angegeben einen Signalhandler mit den Flags SA_RESTART einzurichten.
Und da ist mein Problem. Der bisherige Signalhandler, der weiterhin aktiv bleiben soll, befindet sich in einer anderen Klasse. Die beiden kennen sich nicht. Ich muss das jetzt also irgendwie zusammenführen und dabei erkenne ich, dass ich wohl etwas wesentliches nicht verstanden habe.
Kann ich für jedes Signal einen eigenen Signalhandler einbauen, oder muss ich einem globalen Signalhandler alles beibringen?
Im letzten Fall stellt sich mir die Frage, ob ich die zu behandelnden Signale während der Laufzeit des Programms ändern kann.