2010-09-29 6 views
17

Ich benutze pthread_create um mehrere untergeordnete Threads zu erstellen. Zu einer Zeit möchte der Haupt-Thread alle Kind-Threads töten, oder es wird Segment-Falut geben. Welche Funktion sollte ich verwenden, um das zu beenden? Ich suchte die Antwort von Google und bekam Funktion wie pthread_kill. Aber ich wusste nicht, welches Signal ich dem Kind-Thread schicken sollte, um sie zu töten. Meine Laufumgebung ist RHEL 5.4 und die Programmiersprache ist C.Für pthread, wie Kind Thread aus dem Hauptthread zu töten

+2

wow, kill alle thread, weil es ein segfault sein wird? Machst du Witze? Ich würde niemals durch ein bisschen Code so umgehen. –

+1

Wahrlich, ich gdb den Core-Dump gefunden, wenn der Haupt Thread globale Objekte dekonstruiert wurden. Einige Child-Threads können derzeit eine solche Variable verwenden und der Segmentfehler wird auf meinem Bildschirm ausgegeben. Obwohl die Logik richtig ist und der Segmentfehler keine Auswirkungen auf mein Programm hat, weil es fertig ist. – terry

+2

Korrigieren Sie die Logik. Wenn die anderen Threads immer noch nützliche Arbeit leisten, warum versuchen Sie, das Programm zu beenden? Wenn die anderen Threads diese Objekte auch dann benötigen, wenn 'main' den Gültigkeitsbereich verlässt, warum werden sie auf' main's Stack zugewiesen? –

Antwort

20

Es ist möglich, einen Thread mit pthread_cancel "abzubrechen". Dies ist jedoch in der Regel keine bewährte Vorgehensweise, obwohl unter extremen Umständen wie einer SEGFAULT ein vernünftiger Ansatz verfolgt werden kann.

+1

Es gibt ein Beispiel in dieser URL http://linux.die.net/man/3/pthread_cleanup_push – enthusiasticgeek

+4

Warum wird 'pthread_cancel' nicht als Best Practice betrachtet? Und wenn es nicht beste Praxis ist, was ist? – darnir

6

Sie sollten mit dem Kind gehen zu fork() und halten SIG_TERM jedem Ihrer Fäden, mit

int pthread_kill(pthread_t thread, int sig); 

Eine schnelle Möglichkeit, um loszuwerden, alle Threads (neben dem Haupt) ist senden.
Nicht hyper sauber ...

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

Im Allgemeinen Sie wollen nicht wirklich zu heftig ein Kind Thread töten, sondern wollen, dass es fragen, zu beenden. Auf diese Weise können Sie sicher sein, dass das Kind an einem sicheren Ort aufgibt und alle seine Ressourcen gereinigt werden.

Ich mache dies in der Regel mit einem kleinen Stück gemeinsamen Status zwischen Eltern und Kind, um dem Elternteil zu ermöglichen, jedem Kind eine "Quit-Anfrage" zu übermitteln. Dies kann nur ein boolescher Wert für jedes Kind sein, geschützt durch einen Mutex. Das Kind überprüft diesen Wert regelmäßig (jede Schleifeniteration oder was auch immer Sie in Ihrem Kind-Thread Checkpoints haben). Wenn "quick_request" wahr ist, bereinigt der untergeordnete Thread und ruft pthread_exit.

auf der übergeordneten Seite, die „kill_child“ Routine sieht wie folgt aus etwas:

acquire shared mutex 
set quit_request to true 
pthread_join the child 

Die pthread_join einige Zeit dauern kann, je nachdem, wie häufig das Kind überprüft seine Anfrage zu beenden. Stellen Sie sicher, dass Ihr Entwurf mit der Verzögerung umgehen kann.

+0

Während es allgemein üblich ist, einen Mutex zu erwerben, bevor Speicher geändert wird, der zwischen Threads geteilt wird, bedeutet die Tatsache, dass es sich um ein einzelnes Flag handelt, das auf einen Status ungleich Null (oder false) überprüft wird, dass Sie nicht wirklich benötigen einen Mutex greifen. In diesem Fall kann wirklich nicht viel aus der Datenkohärenzperspektive schief gehen. –

+2

@Brent: [Diese Frage] (http://stackoverflow.com/questions/21183261/is-a-race-condition-possible-when-only-one-thread-writes-to-a-bool-variable-in -c) zeigt ein Beispiel, bei dem sogar ein einziges einmal geschriebenes Flag nach Compiler-Optimierungen zu einer Race-Bedingung führen kann. – dshepherd

+0

Schön, das funktioniert wunderbar. – djthoms

2

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

int _fCloseThreads;

Setzen Sie es auf 1, wenn die Ausführung der Threads beendet werden soll. Lassen Sie die Threads diese Variable in ihrer "Schleife" überprüfen und beenden Sie sie, 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 Join verwenden. Eine andere Möglichkeit besteht darin, einen Zähler zu erhöhen, wenn ein Thread in seinen Thread-Prozess eintritt, und den Zähler dann zu beschädigen, wenn er beendet wird. Der Zähler müsste eine globale Art sein. Verwenden Sie gcc atomare Ops auf dem Zähler. Der Hauptthread kann nach dem Setzen von fCloseThreads auf den Zähler warten, um durch Schleifen, Schlafen und Überprüfen der Zählung auf Null zu gehen.

Schließlich könnten Sie pthread_cleanup_push und pop überprüfen. Sie sind ein Modell, das einem Thread erlaubt, irgendwo in seinem Code abzubrechen (verwendet einen longjump) und dann eine endgültige Bereinigungsfunktion aufzurufen, bevor threadproc beendet wird. Sie setzen cleanup_push am oberen Rand von threadproc und cleanup_pop am unteren Rand, erstellen eine Unwind-Funktion, und an bestimmten Abbruchpunkten springt ein Thread, der durch einen Aufruf von pthread_cancel() abgebrochen wurde, zurück zu threadproc und ruft die unwind-Funktion auf.

+1

http://linux.die.net/man/3/pthread_cleanup_push hat ein Beispiel. – enthusiasticgeek

Verwandte Themen