2014-11-03 7 views
5

Wie lösche ich sicher statische C++ - Objekte in dem Fall, wenn mehrere (Posix) Threads exit() parallel aufrufen?sichere statische Destruktoren, wenn mehrere Threads aufrufen exit()

Es scheint in meiner CentOS6 Umgebung, die exit() führt atexit (oder on_exit) Cleanup-Handler durch so etwas wie fct[--cnt]() Aufruf wo cnt die Zahl der Handler registriert ist. Wenn mehrere Threads exit() zur gleichen Zeit aufrufen, haben wir eine Racebedingung in der ungeschützten --cnt-Operation und einige Handler werden möglicherweise mehrfach übersprungen oder aufgerufen (was zu gelegentlichen Abstürzen führt). Also wie kann ich sicherstellen, dass nur eine der exit() Aufrufthreads die Bereinigung und alle anderen stoppen? Beachten Sie, dass das Einfügen eines pthread_mutex_lock() in einen Bereinigungshandler nicht hilft, weil dieser Handler möglicherweise übersprungen wird ...

Leider kann ich nicht vermeiden, dass mehrere Threads exit() anrufen, weil das Code ist, den meine Benutzer schreiben (ich biete eine Bibliothek zu ihnen).

Auf der Suche nach sicheren Ideen, danke!

+1

Worüber genau machen Sie sich Sorgen? Haben Sie etwas in Ihren statisch zugewiesenen Objekten, das (falls ja?) Gebündelt werden muss? Es ist im Allgemeinen sicher, in modernen hochentwickelten Betriebssystemen ohne Säuberung zu beenden. Wenn Sie bereinigen müssen, dann würde ich vorschlagen, dass Sie wahrscheinlich eine bessere Lösung finden müssen, als Ihren Client Code aufrufen beenden - wie implementieren Sie Ihren Code in einer gemeinsam genutzten Bibliothek, und verwenden Sie die Shared Library Cleanup-Funktion, um aufzuräumen, vielleicht ? Oder dokumentieren Sie: "Sie dürfen' exit() 'nicht aufrufen, verwenden Sie' my_safe_exit() '" und beziehen Sie sich darauf, wenn Kunden sich beschweren, dass es nicht funktioniert. –

+0

Zusätzlich zu den oben genannten, was passiert, wenn Ihre Clients abstürzen (Stapelfehler, Seg Fehler) oder Debuggen und Beenden im Debugger ohne Aufruf von Exit überhaupt? –

+0

Ich habe einige statische Objekte, die C++ zerstören wird, aber nicht sicher parallel (Racebedingung in Destruktoren).Diese Bereinigung wird beispielsweise benötigt, um Ablaufverfolgungsdateiströme ordnungsgemäß zu schließen, sodass eine automatische Bereinigung durch das Betriebssystem keine Option ist. – Rainer

Antwort

0

Wenn Sie gcc verwenden, können Sie den Code verwenden, unten eine Reinigungsprozedur zu definieren:

void __attribute__ ((destructor)) my_fini(void); 

Wenn dies Ihr Problem nicht lösen, wie etwa destructor ein einzelnes Objekt mit statischer der Dauer definieren würde sich um deine Aufräumarbeiten kümmern?

1

Es gibt keinen portablen Weg, mehrere Anrufe zu beenden() - weil es nicht definiert ist (Verhalten), was in diesem Fall passiert.

Aber für eine bestimmte Plattform können Sie einen Weg finden, es zu tun. Eine etwas generische Lösung für das "mehrfache Anrufen" ist eine Flagge in Ihren statischen Objekten wie "bin ich schon zerstört". Wie üblich, können Sie dies in einer Vorlage ausblenden:

Jetzt denken Sie daran, alle Ihre statischen Objekte mit dieser Vorlage zu deklarieren. Das ist nur der Kern davon, fügen Sie Glocken und Pfeifen nach Ihrem Geschmack hinzu. Anstelle von std :: unique_ptr <> können Sie boost :: optional <> oder so etwas verwenden.

Ich glaube nicht, dass es eine generische Lösung für "überhaupt nicht aufgerufen" gibt.

Eigentlich würde ich davon abraten, nicht-triviale statische Objekte in Multi-Thread-Umgebung zu haben. Also, haben Sie nur statische PODs und Objekte mit streng eingeschränkten Destruktoren (abhängig davon, was an dieser Stelle in Ihrer Umgebung sicher ist - d. H. Schließen von Dateigriffen ist in den meisten Umgebungen OK).

Verwandte Themen