was ist los mit alarm()? [gelöst]
-
Ich krieg nun echt bald die Krise! Ich möchte mir ein tool basteln, welches einen bestimmten port auf einem server scant und je nach Erreichbarkeit dieses ports was tut.
Soweit so gut, bis auf das Signal funktioniert nun eigentlich alles. Das einzige Problem ist, dass anscheinend der manuell gesetzte alarm einfach ignoriert wird. Ich versteh nicht weshalb!#include <errno.h> #include <stdlib.h> #include <signal.h> #include <stdio.h> #include <unistd.h> #include "pscan.h" void send_alarm( pid_t caller ) { if( -1 == kill( caller, SIGALRM ) ) { printf("Error in send signal (%d): %s\n", caller, strerror( errno ) ); exit( EXIT_FAILURE ); } } int main(int argc, char** argv) { const long TIMEOUT_ = 1; /* Block the alarm signal so we can accept it */ sigset_t sigset; sigemptyset( &sigset ); sigaddset( &sigset, SIGALRM ); sigprocmask( SIG_BLOCK, &sigset, NULL ); pscan_t scandat; scandat.destination = "medulis.nigel"; scandat.port = 636; /* Create a pipe so we can exchange data from child to parent */ int pipe_fd[2]; pipe( pipe_fd ); /* pipe_fd[0] -> read, pipe_fd[1] -> write */ int sig, scanres; pid_t pid_main = getpid(); switch( fork() ) { case -1: /* Error */ printf( "Error in fork(): %s \n", strerror( errno ) ); exit( EXIT_FAILURE ); case 0: /* Child */ close( pipe_fd[0] ); pscan( &scandat, pipe_fd[1], &send_alarm, pid_main ); exit( EXIT_SUCCESS ); default: /* Parent */ close( pipe_fd[1] ); break; } /* Set timeout */ alarm( TIMEOUT_ ); /* Catch signal, from main process (if timeout occured) or from from child (callback) */ if( 0 != sigwait( &sigset, &sig ) ) { printf( "Error in sigwait: %s \n", strerror( errno ) ); exit( EXIT_FAILURE ); } read( pipe_fd[0], (char *)(&scanres), sizeof( scanres ) ); if( 0 != scanres ) printf("Port is not reachable!\n"); else printf("Port is reachable!\n"); exit( EXIT_SUCCESS ); }
An der Stelle, an welcher die Funktion pscan nun hängt, da keine Verbindung zustande kommen kann, sollte der alarm des Hauptprozesses hier innert einer sekunde erfolgen, das Signal ankommen und das Programm seinen Dienst weiterführen. Mitnichten! Ich warte rund 10 Sekunden, bis das Programm abricht, dass der Port nicht erreichbar ist. Kann mir jemand erklären, weshalb das alarm( TIMEOUT_ ) (hier TIMEOUT_ = 1) nicht ausgeführt wird, resp. weshalb das Signal nicht ankommt? Superseltsam ist zudem, dass wenn der Port tatsächlich erreichbar ist, endet das Programm sofort mit der Meldung, dass der Port erreichbar ist, was bedeutet, dass der callback aus dem Kindsprozess aufgerufen wird und der Alarm im Hauptprozess ankommt.
Ich versteh die Welt nicht mehr!
-
Sorry!!! Da steckten tatsächlich einige Überlegungsfehler drin! Ist eigentlich logisch, dass das Programm nicht abbricht, da der Kindsprozess ja noch läuft...
argh! Also das ganze hab ich folgendermassen gelöst:
Sobald der Kindsprozess startet, schreibt der seine Prozess ID in die pipe und sendet dem Hauptprozess ein Alarmsignal, woraufhin dieser die Prozess ID des Kindsprozesses aus der pipe liest. Danach wird im Hauptprozess der alarm gesetzt und ein weiteres Mal auf das Signal gewartet. Sobald dieses eintrifft, sei dies vom Kindsprozess oder vom Elternprozess, wird mittels kill geprüft, ob der Kindsprozess noch existiert und falls ja, dieser mit einem SIGTERM beendet. Hernach greift der Elternprozess noch ein letztes Mal auf die pipe zu und entnimmt der den Rückgabewert des Kindsprozesses. Sollte der Kindsprozess den Rückgabewert noch nicht geschrieben haben, liegt dieser auch nicht vor und das Ergebnis kann nicht verifiziert werden, entspricht also einem Nichterfolg. Bloss wenn der Kindsprozess erfolgreich seinen Rückgabewert in die pipe geschrieben hat, kann der Hauptprozess diesen verifizieren und erhält ein erfolgreiches Ergebnis.
Grüsse