Make sure images containing BTranslators are not unloaded early
When a translator is uninstalled, BTranslatorPrivate::_RemoveTranslators is called. This method used to unload the image containing the translator after calling Release() on it resulting in several problems: - If the translator was still busy, e.g. translating something while being installed, it crashed since the image was unloaded even though its refcount was larger than 0. - Applications using code from one of the translators (e.g. its config view) would crash when the translator is uninstalled (this is bug #12005). This problem is now fixed. The roster keeps track of all translators whose image it manages (even if the translator was already removed from the roster). It also keeps a refcount to all images. When a translator's refcount drops to zero and it belonged to a roster at some point, it does not delete itself, but notifies the roster that it is ready to destruct, which then removes it from the roster if the translator is still in it, destroys the translator, decrements the refcount of the image and if the new refcount is zero, unloads the image. All of this is done in a message handler, since if the translator called TranslatorDeleted like before, the unloaded image would be referenced when the stack is walked up. Finally, the DataTranslations preflet is required to Acquire() the translator whose config view it is showing, because otherwise its refcount could be reduced to 0 and the image unloaded. BTranslatorRoster now enables users to acquire a translator by ID. By the time the translator has to be released, it might not be part of the roster anymore though. Since BTranslatorRoster tries not to give out raw pointers to the translators it manages, users who acquire a translator through a roster now are given a BTranslatorReleaseDelegate, which allows for releasing the BTranslator exactly once and then self-destructs. Signed-off-by: Axel Dörfler <[email protected]>
This commit is contained in:
committed by
Axel Dörfler
parent
fdfc54b571
commit
a1eccae96f
@@ -59,6 +59,7 @@ enum {
|
||||
B_VALUE_CHANGED = '_VCH',
|
||||
B_TRANSLATOR_ADDED = '_ART',
|
||||
B_TRANSLATOR_REMOVED = '_RRT',
|
||||
B_DELETE_TRANSLATOR = '_DRT',
|
||||
B_VIEW_MOVED = '_VMV',
|
||||
B_VIEW_RESIZED = '_VRS',
|
||||
B_WINDOW_MOVED = '_WMV',
|
||||
|
||||
@@ -23,6 +23,17 @@ class BView;
|
||||
struct entry_ref;
|
||||
|
||||
|
||||
class BTranslatorReleaseDelegate {
|
||||
public:
|
||||
BTranslatorReleaseDelegate(BTranslator* translator);
|
||||
|
||||
void Release();
|
||||
|
||||
private:
|
||||
BTranslator* fUnderlying;
|
||||
};
|
||||
|
||||
|
||||
class BTranslatorRoster : public BArchivable {
|
||||
public:
|
||||
BTranslatorRoster();
|
||||
@@ -86,6 +97,8 @@ public:
|
||||
translator_id translatorID,
|
||||
BMessage* ioExtension);
|
||||
|
||||
BTranslatorReleaseDelegate* AcquireTranslator(int32 translatorID);
|
||||
|
||||
status_t GetRefFor(translator_id translatorID,
|
||||
entry_ref* ref);
|
||||
bool IsTranslator(entry_ref* ref);
|
||||
|
||||
Reference in New Issue
Block a user