temporaeres schlieszen von stdin/stdout

  • ich habe ein programm das sich per commandline-switch auch in einem daemon modus betreiben laeszt. die daemonize() funktion ist nicht sonderlich spannend, im prinzip ein fork() in dem sich der parent prozess verabschiedet und das child weiter laeuft. zusaetzlich noch ein paar signal-handler, chdir, umask usw. wie ich in einem beispielcode gesehen habe werden fuer den daemon auch alle file deskriptoren geschlossen, was mir recht sinnvoll erscheint. wenn schon daemon, dann gscheit. die anzahl der maximalen deskriptoren hole ich mir per sysconf() und mach dann auf jeden einzelnen ein close(). soweit so gut. nur brauche ich zu einem spaeteren zeitpunkt wieder funktionierende 'stdin' und 'stdout', da ich den output von einem anderen prozess lesen will. auch hier wieder die klassiker aus sysprog (pipe, fork, dup2, close, exec). nur wie komme ich zu diesem zeitpunkt wieder an funktionierende 'stdin' und 'stdout'?

    prinzipiell gibt es 2 moeglichkeiten die mir eingefallen sind:
    *) ich mach alle deskriptoren bis auf stdin/out zu.
    *) ich sichere mir die 2 deskriptoren, schliesze alle bis auf die beiden und mache dann ein freopen.

    beides, vor allem ersteres, moeglichkeiten die funktionieren und fuer meine zwecke absolut ausreichend sind, aber kann es sein, dass man nach dem schlieszen _aller_ deskriptoren keine moeglichkeit mehr hat wieder an neue stdin/outs zu kommen? da weisz doch sicher jemand eine schoene moeglichkeit. aja, das ganze soll ausschlieszlich unter gnu/linux laufen, also portabilitaet ist nicht so wichtig. und ein freopen("/dev/stdout,"w",stdout) funktioniert nicht.

    mfg. kampi

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

    Einmal editiert, zuletzt von Kampi (28. Juni 2008 um 19:29)

  • ich fürchte, auch mit guten heuristiken würde es die von dir gesuchte magische get_stdout()-funktion nicht schaffen zu eruieren, was du denn gerne als neuen stdout hättest (den alten gibts ja dann nicht mehr).

    schau dir mal

    Code
    ls -l /dev/stdout

    an, das erklärt, warum freopen() nicht geht.

    und wie liest du dann von deinem dämon aus über stdin/out von einem anderen prozess daten ein? bzw. wozu brauchst du da stdin/stdout, du kannst ja einfach so ein(e) datei/pipe/socket öffnen. oder anders gefragt, was ist denn bei dir stdin und stdout für den dämon?

    lg,
    michi

  • erstmal danke fuer die antwort.

    ich fürchte, auch mit guten heuristiken würde es die von dir gesuchte magische get_stdout()-funktion nicht schaffen zu eruieren, was du denn gerne als neuen stdout hättest (den alten gibts ja dann nicht mehr).

    sehe ich genau so. es wuerde mich wundern wenn es die magie gaebe, aber ich habe gehofft es kennt vlt. jemand einen C-trick, der mir noch nicht unter gekommen ist.

    i
    schau dir mal

    Code
    ls -l /dev/stdout

    an, das erklärt, warum freopen() nicht geht.

    jop, hab ich gemacht und es ist mir auch vollkommen klar warum es so nicht funktioniert. das einzige was geht ist ein backup machen, dann bis aufs backup closen, mir "/dev/fd/$BACKUP" zusammenbaun und ein freopen machen. aber das waer ja unlustig, ich will ja alle schlieszen, auch das backup ;)


    und wie liest du dann von deinem dämon aus über stdin/out von einem anderen prozess daten ein? bzw. wozu brauchst du da stdin/stdout, du kannst ja einfach so ein(e) datei/pipe/socket öffnen. oder anders gefragt, was ist denn bei dir stdin und stdout für den dämon?

    ich denke das funktioniert nicht so einfach. bitte korrigiert mich wenn ich in sysprog nicht gut aufgepasst habe, aber ich lege die pipe an, forke meinen daemon und rufe dann im parent ein exec auf. ueber das aufgerufene parent programm habe ich nicht wirklich kontrolle, dem kann ich auch nicht sagen dass es auf pfd (den ich durch pipe() erzeugt habe) schreiben soll. dieses programm schreibt einfach auf "seinen" stdout. den hab ich aber vorher geschlossen (weit vor dem fork).

    ich zeigs dir anhand folgendem test-code.
    dummy.c: ueber das programm habe ich keine keine kontrolle, das ist einfach so vorhanden:

    Code
    #include <stdio.h>
    
    
    int main(int argc, char **argv)
    {
        printf("%s spricht\n", argv[0]);
    
    
        return 0;
    }

    daemon.c: so ist ca mein daemon aufgebaut. das daemonize() wird einfach durch das schlieszen der deskriptoren 0-9 simuliert:

    das funktioniert so auch ganz gut wenn man "daemon" startet, nur sobald man die die zwei zeilen fuer das simulierte daemonize auskommentiert spricht gar nix mehr.

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

    3 Mal editiert, zuletzt von Kampi (29. Juni 2008 um 18:41)

  • ich denke das funktioniert nicht so einfach. bitte korrigiert mich wenn ich in sysprog nicht gut aufgepasst habe, aber ich lege die pipe an, forke meinen daemon und rufe dann im parent ein exec auf. ueber das aufgerufene parent programm habe ich nicht wirklich kontrolle, dem kann ich auch nicht sagen dass es auf pfd (den ich durch pipe() erzeugt habe) schreiben soll. dieses programm schreibt einfach auf "seinen" stdout. den hab ich aber vorher geschlossen (weit vor dem fork).

    wieso schließt du den schon vor dem fork()? das parent soll ihn ja weiter erwenden, es würde also reichen, die fds im kind zu schließen, oder habe ich da jetzt was übersehen? nur als warnung, ich schreib auch relativ selten c-programme, und noch seltener systemnahe. :)

    bei meinem letzten dämon hat mir übrigens dieser guide geholfen, gleich alles richtig zu machen:

    http://www.unixguide.net/unix/programming/1.7.shtml

    lg,
    michi

  • wieso schließt du den schon vor dem fork()? das parent soll ihn ja weiter erwenden, es würde also reichen, die fds im kind zu schließen, oder habe ich da jetzt was übersehen?

    berechtigte frage, aber im wirklichen programm gehts imho nicht anders. in dem beispielcode schaut das ganze ziemlich ungeschickt aus, keine frage, aber im richtigen programm "muss" ich schon vorher die deskriptoren zu machen. ich parse am anfang die optionen/argumente mit getopt und sobald "--daemon" daher kommt forke ich das erste mal in den background (insgesamt sind es 3 forks die daherkommen). und erst viel viel spaeter kommt dann die geschichte mit dem lesen eines anderen programms. somit ist es keine option einfach mal zu warten bis ich etwas lesen mag und dann schlau zu forken und dann schlau zu schlieszen. zu dem zeitpunkt hat das programm schon lange als daemon zu laufen, da es zb auch ueber startup-skripte gestarte werden kann. aber wie gesagt, ich werde einfach in daemonize() die notwendigen deskriptoren aurecht erhalten und alles ist im lot.

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

  • berechtigte frage, aber im wirklichen programm gehts imho nicht anders. in dem beispielcode schaut das ganze ziemlich ungeschickt aus, keine frage, aber im richtigen programm "muss" ich schon vorher die deskriptoren zu machen. ich parse am anfang die optionen/argumente mit getopt und sobald "--daemon" daher kommt forke ich das erste mal in den background (insgesamt sind es 3 forks die daherkommen). und erst viel viel spaeter kommt dann die geschichte mit dem lesen eines anderen programms. somit ist es keine option einfach mal zu warten bis ich etwas lesen mag und dann schlau zu forken und dann schlau zu schlieszen. zu dem zeitpunkt hat das programm schon lange als daemon zu laufen, da es zb auch ueber startup-skripte gestarte werden kann. aber wie gesagt, ich werde einfach in daemonize() die notwendigen deskriptoren aurecht erhalten und alles ist im lot.

    jetzt versteh ich es erst ganz :)

    an diesem zeitpunkt würde ich den holzhammer gegen die person einsetzen, die mir derart unschöne vorgaben gemacht hat ;)

    lg,
    michi

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!