Für pthread, So beenden Sie untergeordnete Threads aus dem Hauptthread

Lesezeit: 4 Minuten

Ich verwende pthread_create, um mehrere untergeordnete Threads zu erstellen. Zu einem Zeitpunkt möchte der Hauptthread alle untergeordneten Threads beenden, oder es kommt zu einem Segmentfehler. Welche Funktion soll ich verwenden, um das zu beenden? Ich habe die Antwort von Google gesucht und eine Funktion wie pthread_kill erhalten. Aber ich wusste nicht, welches Signal ich an den untergeordneten Thread senden sollte, um sie zu töten. Meine Laufumgebung ist RHEL 5.4 und die Programmiersprache ist C.

  • Wow, alle Threads beenden, weil es einen Segfault geben wird? Machst du Witze? Ich würde nie ein Stück Code verwenden, das so gehandhabt wird.

    – Jens Gustedt

    29. September 2010 um 14:58 Uhr

  • Ehrlich gesagt habe ich den Core-Dump gdb gefunden, als die globalen Objekte des Haupt-Thread-Ausgangs dekonstruiert wurden. Einige untergeordnete Threads verwenden derzeit möglicherweise eine solche Variable, und auf meinem Bildschirm wird ein Segmentfehler angezeigt. Obwohl die Logik richtig ist und Segmentfehler keine Auswirkungen auf mein Programm haben werden, weil es fertig ist.

    – Frottee

    1. Oktober 2010 um 8:50 Uhr

  • Korrigieren Sie die Logik. Wenn die anderen Threads immer noch nützliche Arbeit leisten, warum versuchen Sie dann, das Programm zu beenden? Wenn die anderen Threads diese Objekte noch benötigen, auch wenn main außerhalb des Gültigkeitsbereichs liegt, warum werden sie zugewiesen mains Stapel?

    – David Schwartz

    30. August 2011 um 13:08 Uhr

Im Allgemeinen möchten Sie einen untergeordneten Thread nicht wirklich gewaltsam beenden, sondern ihn stattdessen zum Beenden auffordern. Auf diese Weise können Sie sicher sein, dass das Kind an einem sicheren Ort aufhört und alle seine Ressourcen aufgeräumt sind.

Ich mache dies im Allgemeinen mit einem kleinen Stück gemeinsamen Zustands zwischen Elternteil und Kind, damit der Elternteil jedem Kind eine „Quittungsanfrage“ mitteilen kann. Dies kann nur ein boolescher Wert für jedes Kind sein, geschützt durch einen Mutex. Das untergeordnete Element überprüft diesen Wert regelmäßig (bei jedem Schleifendurchlauf oder an beliebigen geeigneten Prüfpunkten, die Sie in Ihrem untergeordneten Thread haben). Wenn „quit_request“ wahr ist, räumt der untergeordnete Thread auf und ruft auf pthread_exit.

Auf der Elternseite sieht die „kill_child“-Routine etwa so aus:

acquire shared mutex
set quit_request to true 
pthread_join the child 

Das pthread_join kann einige Zeit dauern, je nachdem, wie oft das untergeordnete Element seine Beendigungsanforderung überprüft. Stellen Sie sicher, dass Ihr Design mit jeder Verzögerung umgehen kann.

  • Während es im Allgemeinen eine gute Praxis ist, einen Mutex zu erwerben, bevor Sie Speicher ändern, der von Threads gemeinsam genutzt wird, bedeutet die Tatsache, dass dies ein einzelnes Flag ist, das auf einen Nicht-Null- (oder falschen) Status überprüft wird, dass Sie dies nicht wirklich müssen nimm einen Mutex. In diesem Fall kann aus Sicht der Datenkohärenz wirklich nicht viel schief gehen.

    – Bernie Habermeier

    26. Juli 2013 um 19:51 Uhr


  • @Brent: Diese Frage zeigt ein Beispiel, bei dem sogar ein einzelnes Flag, das einmal geschrieben wurde, nach Compiler-Optimierungen zu einer Race-Bedingung führen kann.

    – Schäfer

    30. Mai 2015 um 15:27 Uhr

  • Was passiert, wenn der untergeordnete Thread vor dem Aufruf von beendet wird? pthread_join? Muss der Thread nicht garantiert am Leben sein, wenn er verbunden wird?

    – Benjamin Crawford Strg-Alt-Tut

    20. Oktober 2019 um 14:53 Uhr

Benutzer-Avatar
Torak

Es ist möglich, einen Thread mit zu “abbrechen”. pthread_cancel. Dies ist jedoch normalerweise keine bewährte Methode, obwohl es unter extremen Umständen wie einem SEGFAULT als vernünftiger Ansatz angesehen werden kann.

  • Warum ist pthread_cancel nicht als Best Practice angesehen? Und wenn es nicht Best Practice ist, was dann?

    – verdammt

    6. August 2016 um 21:55 Uhr

Sie sollten SIG_TERM an jeden Ihrer Threads senden, indem Sie verwenden

  int pthread_kill(pthread_t thread, int sig);

Eine schnelle Möglichkeit, alle Threads (außer dem Hauptthread) loszuwerden, besteht darin, fork() zu verwenden und mit dem untergeordneten Thread weiterzumachen.
Nicht hypersauber…

  if (fork()) exit(0); // deals also with -1...

Sie können eine globale Variable für das gesamte Programm verwenden.

int _fCloseThreads;

Setzen Sie es auf 1, wenn die Threads die Ausführung beenden sollen. Lassen Sie die Threads diese Variable in ihrer “Schleife” überprüfen und ordentlich beenden, wenn sie auf 1 gesetzt ist. Sie müssen sie nicht mit einem Mutex schützen.

Sie müssen warten, bis die Threads beendet sind. Sie können beitreten verwenden. Eine andere Möglichkeit besteht darin, einen Zähler zu erhöhen, wenn ein Thread in seine Thread-Prozedur eintritt, und den Zähler dann zu verringern, wenn er beendet wird. Der Zähler müsste eine Art Global sein. Verwenden Sie gcc Atomic Ops auf dem Zähler. Der Haupt-Thread kann nach dem Setzen von fCloseThreads darauf warten, dass der Zähler auf Null geht, indem er eine Schleife durchläuft, schläft und die Zählung überprüft.

Schließlich können Sie pthread_cleanup_push und pop auschecken. Sie sind ein Modell, um einem Thread zu erlauben, irgendwo in seinem Code abzubrechen (verwendet einen Longjump) und dann eine abschließende Bereinigungsfunktion aufzurufen, bevor er threadproc beendet. Sie setzen cleanup_push ganz oben in Ihren threadproc und cleanup_pop ganz unten, erstellen eine Unwind-Funktion, und dann springt ein Thread, der durch einen Aufruf von pthread_cancel() abgebrochen wird, an bestimmten Abbruchpunkten zurück zu threadproc und ruft die Unwind-Funktion auf.

1257760cookie-checkFür pthread, So beenden Sie untergeordnete Threads aus dem Hauptthread

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy