• Hallo liebes Forum,

    Ich habe ein Program zu debuggen. :)
    Und zwar handelt es sich dabei um ein OSS Projekt bei dem ich eine Erweiterung schreibe, das Program segfaultet und wird aber vom Framework (es handelt sich um Nagios) wieder gestartet.

    Wie kann ich denn nun die exakte Stelle des Fehlers finden?

    Freue mich sehr ueber Hilfe.

    lg
    david

    I like Toast!

  • Hallo und Danke

    Ich entwickle in C auf einer Ubuntu bzw. RedHat Maschine.

    Auf Frameworks möchte ich verzichten, geht doch sicher mit gdb irgendwie, nur bin ich da noch recht unbedarft.

    I like Toast!

  • Hallo und Danke

    Ich entwickle in C auf einer Ubuntu bzw. RedHat Maschine.

    Auf Frameworks möchte ich verzichten, geht doch sicher mit gdb irgendwie, nur bin ich da noch recht unbedarft.

    normalerweise 'gdb -d sourcedir1 programmname'. der gdb spuckt dir mit 'bt' eine stacktrace aus. wenn er im executable genug debug-info findet (gcc -g) und den quellcode hat (-d flag), siehst du auch die stelle im quellcode, wo der fehler liegt.

    rtm: gdb(1), gcc(1) (suche dort nach der -g option)

    lg,
    michi

  • Dieser Post geht mal davon aus, dass du es irgendwie schaffst, deinen Programmteil von einer Kommandozeile zu starten. Mit Nagios kenn ich mich nicht aus...

    valgrind ist ein ganz guter Tip, und auch wenn es "Framework" genannt wird, ist es keine Magie: Du rufst dein Programm auf der Kommandozeile einfach mit

    Code
    valgrind [mein-programm-und-argumente]


    auf und kriegst Unmengen von Fehlermeldungen darueber, was dein Programm alles falsch macht mit Pointern.

    Mit GDB ist es aehnlich:

    Code
    gdb --args [mein-programm-und-argumente]


    Auf dem Prompt dann mal "run" eingeben. Wenn ein Segfault kommt, wird das Programm gestoppt. Ich verwende dann eigentlich fast immer nur den Befehl "bt", der gibt dir einen Stacktrace, und manchmal "print <foo>", wobei <foo> eine beliebige Expression sein kann, ueblicherweise reicht ein Variablenname. Mit q steigt man wieder aus, fertig.

    Fuer erfolgreiches Debugging sollte dein Programm natuerlich mit Debuggingflags kompiliert werden. -ggdb und eher weniger Optimierungsflags sind eine gute Kombi.

    *plantsch*

  • Eine Frage:

    Zitat

    (...) und den quellcode hat (-d flag), (...)


    Das -d flag nun für gcc oder gdb?
    A:
    man gdb
    -d directory
    Add directory to the path to search for source files.

    Das Problem ist eher dass ichs mit gdb nicht optimal starten kann da sich das Programm automatisch recovered. Nichtsdestotrotz sollt es doch einen Coredump machen oder? Wenn nicht, wie kann ich einen Coredump erzwingen? Ich vermute mal indem ich ulimit auf unlimited setz und das Programm dann mal in der bash starte oder?

    I like Toast!

  • Wenn nicht, wie kann ich einen Coredump erzwingen? Ich vermute mal indem ich ulimit auf unlimited setz und das Programm dann mal in der bash starte oder?


    Ja, ulimit -c unlimited. Aber wenn du das Programm in der bash starten kannst und es verlaesslich jedesmal crasht, brauchst du auch nicht unbedingt einen Coredump, du kannst es gleich im Debugger starten.

    *plantsch*

  • ich verstehe aber noch nicht ganz dein problem. schreibst du ein nagios plugin? die kann man imo (schon laenger her dass ich da was geschrieben habe) standalone von der shell starten. zum gdb gibt es ein vernuenftiges buch das von der gnu-press veroeffentlicht wird. ich habe hier zwar die gedruckte version rum liegen, aber wenn es schon gnu-press ist, wird es das buch wohl online geben. an printf-debugging wirst do ja wohl schon gedacht haben ;)

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

    Einmal editiert, zuletzt von Kampi (5. August 2008 um 10:47)

  • Nein, plugin ist es keines.

    printf debugging is bei der Codezeilenanzahl nicht mehr vernünftig brauchbar, weiß auch gar ned wo ich das erste printf reinsetzen sollte.

    Momentan ist der Fehler leider nicht eindeutig reproduzierbar. Bin mir noch nicht mal sicher ob der Fehler im Nagios NEB Modul oder in den NDO-Utils welche ich gemodded hab auftritt.

    I like Toast!

  • So, nun rennt der Prozess und ca alle 15 Sekunden tritt ein Segfault auf, der Prozess wird aber als Childprozess vom Nagios immer wieder neu gestartet wenn er crashed. Was kann ich nun tun damit ich das debugge?

    Core wird keiner erzeugt bzw weiß ich ned wo der liegt (sollte ja im PWD des Users liegen, Nagios wird aber ueber init skript gestartet)

    I like Toast!

  • Könnte auch eine NULL-PTR Fehler sein. Bei mir wars mal so das ich oder ne library einen Memory-Leak hatte. Konnte keinen Speicher mehr allokieren--> PTR = 0 und somit produzierte das Programm einen Seg-Fault. Also printf s würde ich dort plazieren bevor du viel speicher freigibst allokierst oder viel mit pointern werkst.

    mfg Schakal

  • Danke für deinen gutgemeinten Ratschlag, aber das sind zigtausende Zeilen Code und ich weiß nicht mal ansatzweise wo der Fehler sein könnte, also printfs sind hier nicht der richtige Ansatz. (wie schon weiter oben geschrieben)

    I like Toast!


  • Core wird keiner erzeugt bzw weiß ich ned wo der liegt (sollte ja im PWD des Users liegen, Nagios wird aber ueber init skript gestartet)

    mehr geraten als gewuszt, aber den dump wird er, falls er einen ablegt, im current working directory ablegen. schreib dir das current working directory in ein file (man getcwd). vlt bringt dich das dem debugging ein bissl naeher.

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

  • user haben defaultmaessig ulimit 0 für core file size.

    Hab als root "ulimit -c unlimited" ausgeführt und danach nagios gestartet.

    Nagios wird aber daemonized und rennt unter dem User nagios.

    ich frag mich nun welches ulimit dann gilt, 0 oder unlimited?

    I like Toast!

  • So, nun rennt der Prozess und ca alle 15 Sekunden tritt ein Segfault auf, der Prozess wird aber als Childprozess vom Nagios immer wieder neu gestartet wenn er crashed. Was kann ich nun tun damit ich das debugge?

    Core wird keiner erzeugt bzw weiß ich ned wo der liegt (sollte ja im PWD des Users liegen, Nagios wird aber ueber init skript gestartet)

    du findest die pid des kindprozesses innerhalb der 15 sekunden heraus (ps -ef | grep oder pstree -apu und kill ) und sendest dem prozess ein sigstop

    Code
    kill -STOP [I]pid[/I]

    dann hängst du in ruhe den debugger an den prozess

    Code
    gdb [I]programmname pid[/I]

    und sendest ihm ein sigcont

    Code
    kill -CONT [I]pid[/I]

    meiner meinung nach müsste der debugger den prozess dann an der richtigen stelle anhalten, sodass du mit bt eine stacktrace ausgeben kannst. möglicherweise musst du noch vorher das sourcedir mitgeben, siehe oben..

    edit: bei mir funktioniert das mit dem stoppen nicht, gdb (6-6debian) schreibt einen internal error, assertion failed. bin nicht sicher, ob das nicht ein bug ist, einige mailinglist-einträge deuten darauf hin. wie auch immer, davewood, du kannst eigentlich genausogut schnell den debugger direkt attachen, der hält den prozess dann erst mal an, bis du continue sagst.

    lg

    Einmal editiert, zuletzt von michi204 (6. August 2008 um 20:27)

  • ich hab noch eine idee:

    Code
    strace -f -F programmname

    die -f-option habe ich gerade erst entdeckt, die verfolgt kindprozesse. es gibt auch eine option, um den output dann zu trennen, schau dir mal die manpage an.

    ltrace gibt es auch noch, ist aber hier vermutlich nicht hilfreich.

    lg

  • Danke!

    strace -fp hab ich gestern schon probiert aber der output hat mir nicht weitergeholfen.

    Der Child-Prozess der den Fehler verursacht ist leider nur für eine Sekund oder so da (laut watch 'ps aux|grep nagios') und somit zu kurz als dass ich ihn derwisch

    I like Toast!

  • Der Child-Prozess der den Fehler verursacht ist leider nur für eine Sekund oder so da (laut watch 'ps aux|grep nagios') und somit zu kurz als dass ich ihn derwisch


    Ich steig noch immer nicht ganz durch, wie das mit Nagios funktioniert... aber du hast doch Kontrolle ueber die main-Funktion oder was auch immer der Einstiegspunkt deines fehlerhaften Child-Prozesses ist, oder? Da wuerd ich ganz primitiv einfach ein sleep(60) einbauen, und schon haett ich eine Minute Zeit, die PID herauszufinden und mich anzuhaengen.

    *plantsch*

  • Nagios hat scheinbar eine Schnittstelle wo man Module reinhängen kann. Diese Module werden dann scheints geforked und ausgeführt. (Ich kenn die Schnittstellendefinition nicht)

    Du meinst ein sleep(60) gleich am Beginn von main() würde zu folgendem Verhalten führen:

    (1) ./nagios
    (2) sleep(60)
    (3) nagios forked
    (4) child macht sleep(60) PID existiert bereits und kann ausgelesen werden
    (5) gdb nagios -d /home/nagios/... <PID>

    Versteh ich deine sleep Theorie richtig?

    I like Toast!

Jetzt mitmachen!

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