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:
Adrien Destugues 2014-01-19 12:12:57 +01:00
parent 8efd9b8d00
commit fed5e6126b
3 changed files with 27 additions and 17 deletions

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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;
}