Warten Sie, bis ein losgelöster Thread in C ++ fertig ist

8

Wie kann ich darauf warten, dass ein abgetrennter Thread in C ++ endet?

Ich interessiere mich nicht für einen Exit-Status, ich möchte nur wissen, ob der Thread beendet ist oder nicht.

Ich versuche, einen synchronen Wrapper um ein asynchrones Thirdart-Tool bereitzustellen. Das Problem ist ein merkwürdiger Race-Condition-Crash mit Rückruf. Die Progression ist:

  1. Ich rufe den Dritten an und registriere einen Rückruf
  2. wenn der Dritte fertig ist, benachrichtigt er mich über den Callback - in einem abgetrennten Thread habe ich keine wirkliche Kontrolle darüber.
  3. Ich möchte, dass der Thread von (1) wartet, bis (2) aufgerufen wird.

Ich möchte dies in einen Mechanismus einbinden, der einen blockierenden Anruf bereitstellt. Bisher habe ich:

%Vor%

Soweit ich das beurteilen kann, sollte das funktionieren, und das tut es normalerweise, aber manchmal stürzt es ab. Soweit ich aus der Kerndatei ermitteln kann, ist meine Vermutung in Bezug auf das Problem:

  1. Wenn der Rückruf das Ende von m_done überträgt, wird der Warte-Thread aktiviert.
  2. Der Warte-Thread ist jetzt hier fertig, und Wait ist zerstört. Alle Mitglieder von Wait sind zerstört, einschließlich Mutex und Cond.
  3. Der Callback-Thread versucht, vom Broadcast-Punkt aus fortzufahren, verwendet jedoch jetzt den freigegebenen Speicher, was zu einer Speicherbeschädigung führt.
  4. Wenn der Callback-Thread versucht, zurückzukommen (über dem Level meiner schlechten Callback-Methode), stürzt das Programm ab (normalerweise mit einem SIGSEGV, aber ich habe SIGILL ein paar Mal gesehen).

Ich habe viele verschiedene Mechanismen ausprobiert, um zu versuchen, das zu beheben, aber keiner von ihnen löst das Problem. Ich sehe immer noch gelegentliche Abstürze.

BEARBEITEN : Weitere Details:

Dies ist Teil einer massiven Multithread-Anwendung, daher ist das Erstellen eines statischen Waits nicht praktikabel.

Ich habe einen Test ausgeführt, Wait auf dem Heap erstellt und den Speicher absichtlich ausgeleert (d. h. die Wait-Objekte werden nie freigegeben), und das führte zu keinen Abstürzen. Ich bin mir sicher, dass es ein Problem ist, dass man zu früh die Zuweisung aufheben muss.

Ich habe auch einen Test mit einem sleep(5) nach dem Entsperren in wait ausprobiert, und das verursachte auch keine Abstürze. Ich hasse es jedoch, mich auf einen solchen Klumper zu verlassen.

BEARBEITEN : ThirdParty-Details:

Ich fand das zunächst nicht relevant, aber je mehr ich darüber nachdenke, desto mehr denke ich, dass es das eigentliche Problem ist:

Die Third Party Sachen, die ich erwähnt habe, und warum ich keine Kontrolle über den Thread habe: das benutzt CORBA.

Es ist also möglich, dass CORBA einen Verweis auf mein Objekt länger als beabsichtigt festhält.

    
Tim 15.11.2009, 02:49
quelle

4 Antworten

3

Ja, ich glaube, dass das, was Sie beschreiben, geschieht (Rassenkonflikt bei Aufhebung). Eine schnelle Möglichkeit, dies zu beheben, besteht darin, eine statische Instanz von Wait zu erstellen, die nicht zerstört wird. Dies funktioniert, solange Sie nicht mehr als einen Kellner gleichzeitig haben müssen.

Sie werden diesen Speicher auch dauerhaft verwenden, er wird nicht freigegeben. Aber es sieht nicht so schlecht aus.

Das Hauptproblem ist, dass es schwer ist, die Lebensdauern Ihrer Thread-Kommunikationskonstrukte zwischen Threads zu koordinieren: Sie benötigen immer mindestens ein übrig gebliebenes Kommunikationskonstrukt, um zu kommunizieren, wenn es sicher zu zerstören ist (zumindest in Sprachen ohne Garbage Collection wie C ++) ).

BEARBEITEN : Siehe Kommentare für einige Ideen zum Refcounting mit einem globalen Mutex.

    
Adam Goode 15.11.2009, 02:58
quelle
0

Nach meinem besten Wissen gibt es keinen portablen Weg, einen Thread direkt zu fragen, wenn er ausgeführt wird (d. h. keine Funktion pthread_ ). Was Sie tun ist der richtige Weg, um es zu tun, zumindest so weit wie eine Bedingung, die Sie signalisieren. Wenn Sie feststellen, dass Abstürze, die aufgrund des Wait -Objekts sicher sind, rückgängig gemacht werden, wenn der Thread, der es erstellt, beendet wird (und nicht irgendein anderes subtiles Locking-Problem - all zu häufig), dann Problem ist, dass Sie sicherstellen müssen, dass die Zuordnung von Wait nicht aufgehoben wird, indem Sie von einem anderen Thread als dem, der die Benachrichtigung durchführt, aus verwalten. Setzen Sie es in den globalen Speicher oder ordnen Sie es dynamisch zu und teilen Sie es mit diesem Thread. Am einfachsten haben Sie nicht den Thread warten auf den Speicher für die Wartezeit, haben Sie den Thread zu tun, die warten, es zu besitzen.

    
quark 15.11.2009 03:00
quelle
0

Initialisierst und zerstörst du den Mutex und die Bedingung var richtig?

%Vor%

Stelle sicher, dass du das Wait -Objekt nicht vorzeitig zerstörst - wenn es in einem Thread zerstört wird, während der andere Thread es noch benötigt, wirst du eine Race Condition bekommen, die wahrscheinlich zu einem Segfault führen wird. Ich würde empfehlen, es zu einer globalen statischen Variable zu machen, die bei der Programminitialisierung (vor main() ) erstellt und beim Programm-Exit zerstört wird.

    
Adam Rosenfield 15.11.2009 03:03
quelle
0

Wenn Ihre Annahme richtig ist, dann scheint das Modul eines Drittanbieters fehlerhaft zu sein und Sie müssen sich eine Art Hack ausdenken, damit Ihre Anwendung funktioniert.

Statisch Wait ist nicht möglich. Wie wäre es mit Wait pool (es kann sogar auf Nachfrage wachsen)? Verwenden Sie eine Anwendung, die einen Thread-Pool verwendet? Es besteht zwar immer noch die Möglichkeit, dass das gleiche Wait wiederverwendet wird, während das Modul des Drittanbieters es noch verwendet. Aber Sie können diese Chance minimieren, indem Sie freie Wartezeiten in Ihrem Pool richtig stopfen.

Haftungsausschluss: Ich bin in keiner Weise ein Experte in Thread-Sicherheit, so betrachten Sie diesen Beitrag als ein Vorschlag von einem Laien.

    
BostonLogan 15.11.2009 04:35
quelle

Tags und Links