LocaleRoster: race condition on catalog loading.
Using a vint32 isn't enough to safely decide if the catalog is initialized or not. Use init_once features instead.
This commit is contained in:
parent
8efd9b8d00
commit
fed5e6126b
@ -6,6 +6,8 @@
|
||||
#define _LOCALE_ROSTER_H_
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <Entry.h>
|
||||
#include <String.h>
|
||||
|
||||
@ -98,7 +100,7 @@ protected:
|
||||
|
||||
private:
|
||||
static BCatalog* _GetCatalog(BCatalog* catalog,
|
||||
vint32* catalogInitStatus);
|
||||
int32* catalogInitStatus);
|
||||
|
||||
status_t _PrepareCatalogEntry(const entry_ref& ref,
|
||||
BString& signature, BString& context,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>.
|
||||
* Copyright 2010-2014, Adrien Destugues <pulkomandy@pulkomandy.tk>.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -7,9 +7,11 @@
|
||||
#include <Catalog.h>
|
||||
#include <LocaleRoster.h>
|
||||
|
||||
#include <locks.h>
|
||||
|
||||
|
||||
static BCatalog sCatalog;
|
||||
static vint32 sCatalogInitOnce = false;
|
||||
static int32 sCatalogInitOnce = INIT_ONCE_UNINITIALIZED;
|
||||
|
||||
|
||||
BCatalog*
|
||||
@ -28,7 +30,7 @@ BLocaleRoster::GetCatalog()
|
||||
namespace BPrivate{
|
||||
void ForceUnloadCatalog()
|
||||
{
|
||||
sCatalogInitOnce = false;
|
||||
sCatalogInitOnce = INIT_ONCE_UNINITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <TimeZone.h>
|
||||
|
||||
#include <ICUWrapper.h>
|
||||
#include <locks.h>
|
||||
|
||||
// ICU includes
|
||||
#include <unicode/locdspnm.h>
|
||||
@ -515,16 +516,10 @@ BLocaleRoster::GetLocalizedFileName(BString& localizedFileName,
|
||||
}
|
||||
|
||||
|
||||
BCatalog*
|
||||
BLocaleRoster::_GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
|
||||
static status_t
|
||||
_InitializeCatalog(void* param)
|
||||
{
|
||||
// This function is used in the translation macros, so it can't return a
|
||||
// status_t. Maybe it could throw exceptions ?
|
||||
|
||||
if (*catalogInitStatus == true) {
|
||||
// Catalog already loaded - nothing else to do
|
||||
return catalog;
|
||||
}
|
||||
BCatalog* catalog = (BCatalog*)param;
|
||||
|
||||
// figure out image (shared object) from catalog address
|
||||
image_info info;
|
||||
@ -540,13 +535,24 @@ BLocaleRoster::_GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return catalog;
|
||||
return B_NAME_NOT_FOUND;
|
||||
|
||||
// load the catalog for this mimetype and return it to the app
|
||||
// load the catalog for this mimetype
|
||||
entry_ref ref;
|
||||
if (BEntry(info.name).GetRef(&ref) == B_OK && catalog->SetTo(ref) == B_OK)
|
||||
*catalogInitStatus = true;
|
||||
if (BEntry(info.name).GetRef(&ref) == B_OK && catalog->SetTo(ref) == B_OK);
|
||||
return B_OK;
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
BCatalog*
|
||||
BLocaleRoster::_GetCatalog(BCatalog* catalog, int32* catalogInitStatus)
|
||||
{
|
||||
// This function is used in the translation macros, so it can't return a
|
||||
// status_t. Maybe it could throw exceptions ?
|
||||
|
||||
__init_once(catalogInitStatus, _InitializeCatalog, catalog);
|
||||
return catalog;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user