C++ und SIGTERM usw.; wie funzt das eigentlich

  • Hi!


    Ich hätte mal ne recht allgemeine Frage zur C++-Programmierung, vielleicht kann mich da ja jemand mit ein paar Worten und ev. ein paar Links erleuchten.


    Bei den "dvb-apps" der DVB-Treiber gibt es das Programm "test_vevent", das bei Änderung der Auflösung im Videostrom eine Meldung ausgibt. Das ganze würde ich gerne in mein Plugin "videosystem" übernehmen.


    So, in diesem Test-Programm ist das über poll gelöst und die Schleife sieht prinzipiell so aus:

    Code
    for (;;) {
       // ein wenig Code
       rc = poll(pfd, 1, -1);
       // ein wenig Code
    }


    Im Code wird dann immer an dieser Codestelle gewartet bis sich was ändert. Jetzt könnte ich das ganze einfach in einen Thread einbauen, den ich beim Starten von VDR und dem Plugin aktiviere, doch wie beende ich dann so einen Thread wieder richtig. Im Normalfall wird der Thread ja immer durchlaufen und es gibt diese "do { } while (active);"-Abfrage. Das ist ja hier nicht der Fall weil der Code ja an der Stelle "hängt".


    Das brachte mich auch dazu zu überlegen, wie das eigentlich in diesem test-Programm abläuft und hier ist ja kein Signal-Handling vorhanden. Heißt das dann, dass beim Drücken von <STRG> C auf der Konsole einfach der Code an der aktuellen Stelle unterbrochen wird?
    Im VDR wird ja das ganze irgendwie gehandelt, damit beim Beenden die ganzen Konfigs usw. gespeicher werden können.


    Doch irgendwie bringt mich das alles nicht so recht weiter. Muss ich dem Thread irgendwie ein SIGTERM schicken damit der alles stehen und liegen lässt und sich beendet? Was ist dann mit den geöffneten Handels?


    Ihr seht, ich habe keine Ahnung von dem Zeug (musste mich noch nie damit beschäftigen) und wäre für jegliche Infos dankbar.


    Gruß,
    Brougs78

    - -- --- ================================================================ --- -- -
    Antec Fusion, Intel E5200, Asus P5N7A-VM (VDPAU), DD CineS2 v6 + DD DuoFlex CI // yavdr-0.6.1
    - -- --- ================================================================ --- -- -

  • Zitat

    Doch irgendwie bringt mich das alles nicht so recht weiter. Muss ich dem Thread irgendwie ein SIGTERM schicken damit der alles stehen und liegen lässt und sich beendet? Was ist dann mit den geöffneten Handels?


    Ja, musst du. Der aufrufende Thread muss diesen killen. Du hast auch wegen des Pollings keine andere Möglichkeit. Ich muss zugeben, dass ich mir Threads in Linux noch nie angeschaut habe, aber funktionieren müsste das so, dass wenn der Thread gestartet wird, du ein Handle auf diesen erhälts, damit sollte sich dann der Thread auch wieder mit einer Funktion ala KillThread(Handle vom Thread) beenden lassen. In deinem Beispiel dürfte das einfache Killen des Threads auch keine Probleme bereiten, da du ja keine Files beim beenden Speichern möchtest, so wie es VDR macht...


    Gruß
    Dagget

    YaVDR 0.5
    1x TT 1600 DVB-S2, 1x FF DVB-S 2300, 1x Nova-S

    Einmal editiert, zuletzt von Dagget ()

  • Hi,


    Warum nicht per timeout = 250ms intervallweise warten ?




    z.T. SIGTERM müsstest Du einen Signalhandler anlegen, wie es im glcdbase/showpic gemacht wurde.



    Aber bist Du sicher das per signal ein Thread selektiv gestoppt werden sollte !?
    Ich bevorzuge obrige Methode des Verzicht auf unendliche Wartezeiten...


    Andreas

  • Ich hab das so verstanden, das poll() die wartende Funktion ist in der das eigentliche polling in einer Schleife stattfindet. Sonst ist deine Variante natürlich sinnvoller.


    In thread.h habe ich folgendes gefunden, um Threads "hart" zu beenden:

    Code
    void Cancel(int WaitSeconds = 0);
           ///< Cancels the thread by first setting 'running' to false, so that
           ///< the Action() loop can finish in an orderly fashion and then waiting
           ///< up to WaitSeconds seconds for the thread to actually end. If the
           ///< thread doesn't end by itself, it is killed.
  • Hi!


    Danke für die Antworten. Also dann bevorzuge ich natürlich auch eine begrenzte Wartezeit. ;D
    Habe mir die Syntax von poll nicht angeschaut ... hab das nur so im test-Code gesehen.


    Gruß,
    Brougs78

    - -- --- ================================================================ --- -- -
    Antec Fusion, Intel E5200, Asus P5N7A-VM (VDPAU), DD CineS2 v6 + DD DuoFlex CI // yavdr-0.6.1
    - -- --- ================================================================ --- -- -

  • Generell ist die Methode, poll() mit Timeout zu verwenden, die bequemste. Es gibt aber noch eine weitere Methode, um den Thread auch ohne Timeout schnell zu beenden: poll() kehrt auch bei ankommenden Signalen zum Aufrufer zurück, mit EINTR-Fehlercode. Senden kann man solch ein Signal mittels pthread_kill().


    Gruß,


    Udo

  • Hi,


    Threads und Signale sind nicht ganz so einfach zu programmieren. Man muss einen Thread für den Empfang der Signale bestimmen. Ansonsten weiß man nicht, an welchen Thread das Signal geschickt wird!


    Einzelne Thread kann man mit einem pthread_kill terminieren. Ist aber normalerweise nicht nötig, wenn man ein saubers Konzept hat.


    Stirbt der Hauptthread (der Teil, in dem int main (argc, argv) steht), dann sterben auch alle erzeugten Threads. Alle "Handles" (wohl meistens sockets) werden dabei geschlossen.


    Darüber gibt es sehr interessante Bücher.


    Viele Grüße
    KdF

  • Aus meiner Sicht ist es die sauberste Lösung, eine Meldung zu definieren, die zum Beenden des Threads führt. Das externe Töten des Threads ist zwar möglich, aber aus meiner Sicht eine sehr unsaubere Vorgehensweise.


    Beim Beenden einer Applikation mag das ja noch angehen, jedoch nicht wenn man das zur Laufzeit macht (Beispiel: VDR->pluginloader-Plugin). Durch das externe Killen ist nicht sichergestellt, das alle Resourcen freigegeben wurden, da diese an die Applikation und nicht an den Thread gebunden sind. Nebeneffekte können zum Beispiel sein, das Datenbank-Sessions nicht mehr zugeteilt werden oder bestimmte Devices nicht mehr geöffnet werden können, weil der Treiber bereits ein exklusives Handle vergeben hat. Das kennt dann keiner mehr, aber der Treiber kann das nicht wissen.


    Sauber wäre das Definieren einer Ausstiegsmeldung. Wenn jetzt jemand den Thread nach Hause schicken will, wird die Meldung abgesetzt und anschließend auf das Ende gewartet.


    Code
    void setExitRequest(int code)
    {
        sendMessage(new ThreadExitRequest(code));
        join(); // warte bis das OS den Thread entsorgt hat
    }


    Innerhalb des Threads führt das Aufreten der entsprechenden Methode dann zum Setzen der Ausstiegsbedingung und damit zum Threadende.


    Das Weglassen des join() ist aus meiner Sicht auch wieder unsaubere Programmierung, da hier mit einem undefinierten Zustand gearbeitet wird. Keiner kann sagen ob beim bereits alle Resourcen frei sind, oder ob irgendwas noch unterwegs. Das lädt zu einer zeitintensiven Fehlersuche geradezu ein.



    dierk

Jetzt mitmachen!

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