Daemon erstellt keine Threads mehr



  • Hallo,

    ich habe einen Prozess, der nimmt Verbindungen entgegen(accept()) und startet dann ein Thread welchem er die Verbindung(Socket) uebergibt und dieses Thread kuemmert sich dann um die Verarbeitung.

    Dies funktioniert alles solange der Prozess im Vordergrund laeuft, also _kein_ Daemon ist.

    Wenn ich aber den Prozess zu einen daemon mache(siehe unten) dann erstellt pthread_create() keine Threads mehr. Es wird _keine_ Fehlermeldung ausgegeben! D.h. pthread_create() gibt 0 zurueck(=kein Fehler).

    So wird der Prozess ein Daemon:

    if(setgid(global.id) == -1)
        errorprint(FATAL, "Error: setgid\(2): %s\n", strerror(errno));
    if(setuid(global.gid) == -1)
        errorprint(FATAL, "Error: setuid\(2): %s\n", strerror(errno));
    if((pid = fork()) < 0)
        errorprint(FATAL, "Error: fork\(2): %s\n", strerror(errno));
    else if(pid != 0)
        exit(0);
    if(setsid() == -1)
        errorprint(FATAL, "Error: setsid\(2): %s\n", strerror(errno));
    umask(0);
    

    und so moechte ich ein neues Thread erstellen:

    if((pthread_create(&reqcur->tt, NULL, (void *)handle, reqcur)) != 0)
    	errorprint(ERRLOG, "pthread_create: %s\n", strerror(errno));
    

    Was soll ich machen?
    Wie kann ich feststellen wo der Fehler ist?

    Ich schaetze es ist etwas bei dem "zum daemon werden" falsch, da das gesamte programm ohne diesen Teil wunderbar funktioniert. Nur sehe ich darin keinen fehler! Hab auch schon in diversen Buechern nachgeschlagen aber nichts. Auch hier im Board habe ich nichts gefunden.

    [EDIT]

    OK, noch weitere Informationen:
    Also ich bau zu diesem Server eben eine Verbindung auf(mit Telnet) und sende ein paar Zeichen zu diesem Server. Nun dieser reagiert aber nicht!
    Wenn ich netstat -a aufrufe sehe ich das der Server etwas in der Recv-Queue stehen hat(meine Zeichen!).
    Vielleicht hilft das jemanden weiter!

    Der Behauptung das Thread startet sich nicht nehme ich daher:
    Ich gebe einen fprintf() am Anfang der Thread-Funktion(noch vor allem!) und auch dieser wird nicht abgearbeitet!
    Daraus schliesze ich, dass es nicht nur am Socket liegen kann sondern dass das ganze Thread irgendwie "kaputt" ist, oder?

    Sollte jemand noch mehr Informationen brauchen dann sagt mir das bitte!

    [/EDIT]

    vielen Dank



  • Ist schon wirklich sehr merkwürdig. Vielleicht funktioniert es ja, wenn Du den Prozess mittels "int daemon(int nochdir, int noclose);" zum Deamon machst, ein fork muss natürlich trotzdem her. Aber eigentlich sollte das nichts ändern.
    Ich würde mal statt eine printf-Ausgabe etwas anderes versuchen, z.B. eine Datei anlegen. Vielleicht besitzt Du als Daemon gar keine Standard-Ausgabe, sondern es wird auf /dev/null gelenkt? Aber hoffentlich haben andere Leuts hier mehr Ahnung um Dir zu helfen.



  • Du machst deinen Prozess nicht zu Daemon!

    Für einen Daemon sind definitiv 2 fork notwendig da der Childprozess zurückkehren muss.



  • wischmop2 schrieb:

    Vielleicht funktioniert es ja, wenn Du den Prozess mittels "int daemon(int nochdir, int noclose);" zum Deamon machst,

    So sieht das aus.
    auferufen wird mit

    daemon(0, 0);

    und schon ist der Process ein Daemon

    void closeall(int fd)
    {
        int fdlimit = sysconf(_SC_OPEN_MAX);
        while (fd < fdlimit)
        close(fd++);
     }
    
    /* ---------------------------------------------------------- */
    int daemon(int nochdir, int noclose)
    {
        switch (fork())
        {
    	case 0:  break;
            case -1: return -1;
            default: _exit(0);          
        }
    
        if (setsid() < 0)               
        return -1;
    
        switch (fork())
        {
    	case 0:  break;
            case -1: return -1;
            default: _exit(0);
        }
    
        if (!nochdir)
           chdir("/");
    
        if (!noclose)
        {
    	closeall(0);
            open("/dev/null",O_RDWR);
            dup(0); dup(0);
        }
    
         return 0;
    }
    


  • @Unix-Tom: daemon gibt es unter Linux in der unistd.h/glibc und eine Manpage existiert dazu auch. ("man daemon" oder http://jamesthornton.com/linux/man/daemon.3.html)



  • Hallo,

    erstmal Danke fuer die Hilfen!
    Also ich habe es mit dieser Funktion von Unix-Tom probiert auch mit der Funktion der Standardbibliothek. Ich arbeite unter FreeBSD aber auch hier ist diese daemon(3)-Funktion verfuegbar.

    Dies hat aber alles leider nichts genuetzt! Genau das selbe Problem wie vorher. Sobald ich die Funktion, oder den Code-Teil, auskommentiere funktioniert alles wie es soll. Nur sobald dieser Teil dazukommt geht gar nichts mehr.

    Ich kann auch z.B. vor dem Aufruf von pthread_create() mit send() etwas an den Telnet-Client schicken. Aber das Thread wird eben nicht richtig gestartet(ist meine Vermutung).

    Wegen printf(), ja ich habe es natuerlich auch probiert dass ich in eine Datei schreibe aber auch das wollte das Thread nicht machen.

    Also _vor_ dem "daemonisieren" wurde schon chdir() und gegebenen Falls auch chroot() aufgerufen, beide Funktion Rueckgabewert ueberprueft!
    Dann gibt das Programm etwas aus(mit printf()) und dann werden die gesamten Socket Einstellungen vorgenommen. Alles "Standard" also nichts besonderes irgendwie.
    Dann sollte eben der Codeabschnitt der "Daemonisierung" aufgerufen werden und dann geht es weiter in die for(;;) schleife.
    Dort wird mit Hilfe von Mutex zuerst eine Variable hinaufgezaehlt und dann kommt eben der typische accept() aufruf und dann pthread_create().
    Das wars. Und das Thread wird einfach nicht gestartet obwohl keine Fehlermeldung(Rueckgabewert) zurueckgegeben wird der auf einen Fehler schlieszen wuerde!

    Ja etwas komisch ist das Ganze schon!

    Gibts vielleicht irgend einen "Starte kein Thread"-Variable bei Daemon die man irgendwie abschalten muss oder sowas? Also eine Blockierung?

    Naja, falls jemanden noch etwas einfaellt postet bitte hier!
    Falls noch Informationen noetig sind sagt es einfach!

    vielen Dank



  • Nein, das sollte schon alles so funktionieren und somit wird Dir hier wahrscheinlich auch keiner sagen können, wo der Fehler ist. Dann muss der Fehler an einer ganz anderen Stelle liegen, so etwas hat man ja häufig (in C/C++), dass sich ein Fehler erst an einer Stelle bemerkbar macht, wo man dann vergeblich sucht.
    Generell kannst Du in einem solchen Fall so vorgehen: Sicherheitskopie von aktuellen Projekt machen und dann den Code zurück bauen, wenn notwendig soweit, bis wirklich nur noch eine reine while(accept())-Schleife übrig bleibt und beobachten, wann der Fehler nicht mehr auftritt - natürlich die Daemon-Geschichte drin lassen.
    Grundsätzlich fällt mir nur noch eine Sache zu fork() ein, was aber eingentlich keine Auswirkung bei Dir hat - es sei denn, Du hast uns noch ein paar andere Fork's verschwiegen oder Du machst noch etwas vor der Daemonisierung:
    Fork gabelt den laufenden Prozess ja auf. Wenn vor dem Fork ein Socket, eine Pipe, etc. geöffnet wurde, dann können nach dem Fork nicht einfach beide Prozesse z.B. aus dem Socket lesen. Einer von beiden muss den Filediskriptor mittels close(int fd) schliessen, sonst hat man nämlich z.B. halb offene Pipes. Aber dies gilt wie schon gesagt bei fork, nicht bei clone, also Threads.



  • Hallo,

    also Problem geloest!
    Ich moechte nur die "Loesung" hier kurz posten falls jemand anderes auch diese Problem hat.

    Also man muss die Socket Einstellungen und Socket Sachen _nach_ dem "daemonisieren" machen!

    dann gehts...

    wird wahrscheinlich mit dem zusammenhaengen was wischmop2 gesagt hat!

    Ich habe das Phaenomen nicht genauer untersucht, bei mir funktioniert es jetzt so...

    mfg



  • Dann hast du eine Fehler gemacht wie wischmop2 geschrieben hat. IMHO hatte ich schon Daemons die auf einen Socket LISTEN hatten. Bei Connect eines Clients habe ich mittels Fork eines Prozess erstellt der die Clientkomuni. weiter gemacht hat. Der Elterproz. ist wieder auf Listen gegangen.



  • nochdir="no chdir"
    chdir="change directory"
    -> nochdir="no change directory"


Anmelden zum Antworten