Fix race condition reading filename/string from config var

This commit is contained in:
rdb 2016-07-12 14:47:20 +02:00
parent 7b7bf93118
commit 69f15258e4
5 changed files with 49 additions and 11 deletions

View File

@ -26,6 +26,7 @@ This issue fixes several bugs that were still found in 1.9.2.
* Fix issues with certain Cg shader inputs in DX9 * Fix issues with certain Cg shader inputs in DX9
* Support uint8 index buffers in DX9 * Support uint8 index buffers in DX9
* Fix occasional frame lag when loading a big model asynchronously * Fix occasional frame lag when loading a big model asynchronously
* Fix race condition reading string config var
------------------------ RELEASE 1.9.2 ------------------------ ------------------------ RELEASE 1.9.2 ------------------------

View File

@ -23,8 +23,16 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void ConfigVariableFilename:: void ConfigVariableFilename::
reload_cache() { reload_cache() {
// NB. MSVC doesn't guarantee that this mutex is initialized in a
// thread-safe manner. But chances are that the first time this is called
// is at static init time, when there is no risk of data races.
static MutexImpl lock;
lock.acquire();
// We check again for cache validity since another thread may have beaten
// us to the punch while we were waiting for the lock.
if (!is_cache_valid(_local_modified)) {
nassertv(_core != (ConfigVariableCore *)NULL); nassertv(_core != (ConfigVariableCore *)NULL);
mark_cache_valid(_local_modified);
const ConfigDeclaration *decl = _core->get_declaration(0); const ConfigDeclaration *decl = _core->get_declaration(0);
const ConfigPage *page = decl->get_page(); const ConfigPage *page = decl->get_page();
@ -35,4 +43,8 @@ reload_cache() {
_cache = Filename::expand_from(decl->get_string_value()); _cache = Filename::expand_from(decl->get_string_value());
ExecutionEnvironment::clear_shadow("THIS_PRC_DIR"); ExecutionEnvironment::clear_shadow("THIS_PRC_DIR");
mark_cache_valid(_local_modified);
}
lock.release();
} }

View File

@ -155,8 +155,7 @@ INLINE const string &ConfigVariableString::
get_value() const { get_value() const {
TAU_PROFILE("const string &ConfigVariableString::get_value() const", " ", TAU_USER); TAU_PROFILE("const string &ConfigVariableString::get_value() const", " ", TAU_USER);
if (!is_cache_valid(_local_modified)) { if (!is_cache_valid(_local_modified)) {
mark_cache_valid(((ConfigVariableString *)this)->_local_modified); ((ConfigVariableString *)this)->reload_cache();
((ConfigVariableString *)this)->_cache = get_string_value();
} }
return _cache; return _cache;
} }

View File

@ -13,3 +13,26 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#include "configVariableString.h" #include "configVariableString.h"
////////////////////////////////////////////////////////////////////
// Function: ConfigVariableString::reload_cache
// Access: Published
// Description: Refreshes the variable's cached value.
////////////////////////////////////////////////////////////////////
void ConfigVariableString::
reload_cache() {
// NB. MSVC doesn't guarantee that this mutex is initialized in a
// thread-safe manner. But chances are that the first time this is called
// is at static init time, when there is no risk of data races.
static MutexImpl lock;
lock.acquire();
// We check again for cache validity since another thread may have beaten
// us to the punch while we were waiting for the lock.
if (!is_cache_valid(_local_modified)) {
_cache = get_string_value();
mark_cache_valid(_local_modified);
}
lock.release();
}

View File

@ -51,6 +51,9 @@ PUBLISHED:
INLINE string get_word(int n) const; INLINE string get_word(int n) const;
INLINE void set_word(int n, const string &value); INLINE void set_word(int n, const string &value);
private:
void reload_cache();
private: private:
AtomicAdjust::Integer _local_modified; AtomicAdjust::Integer _local_modified;
string _cache; string _cache;