Skip to content
Snippets Groups Projects
Commit adf6d0cb authored by Eric Cano's avatar Eric Cano
Browse files

Fixed race condition in castor::BaseObject::services().

The lazy initialization of member s_servicesKey was racing with its usage in services().
As the laziness is not really needed, replaced it with a init-time initialization in a small wrapper class.
parent c63d910c
Branches
Tags
No related merge requests found
......@@ -35,8 +35,7 @@
// static values initialization
//------------------------------------------------------------------------------
castor::Services* castor::BaseObject::s_sharedServices(0);
pthread_key_t castor::BaseObject::s_servicesKey(0);
pthread_once_t castor::BaseObject::s_servicesOnce = PTHREAD_ONCE_INIT;
castor::BaseObject::pthreadKey castor::BaseObject::s_servicesKey;
//------------------------------------------------------------------------------
// constructor
......@@ -68,38 +67,14 @@ castor::Services* castor::BaseObject::svcs()
return services();
}
//------------------------------------------------------------------------------
// makeServicesKey
//------------------------------------------------------------------------------
void castor::BaseObject::makeServicesKey()
throw (castor::exception::Exception) {
int rc = pthread_key_create(&s_servicesKey, NULL);
if (rc != 0) {
castor::exception::Exception e(rc);
e.getMessage() << "Error caught in call to pthread_key_create";
throw e;
}
}
//------------------------------------------------------------------------------
// services
//------------------------------------------------------------------------------
castor::Services* castor::BaseObject::services()
throw (castor::exception::Exception) {
// make a new key if we are in the first call to this
{
const int rc = pthread_once(&castor::BaseObject::s_servicesOnce,
castor::BaseObject::makeServicesKey);
if (rc != 0) {
castor::exception::Exception e(rc);
e.getMessage() << "Error caught in call to pthread_once";
throw e;
}
}
castor::Services *services =
(castor::Services *)pthread_getspecific(s_servicesKey);
// If this is the first time this thread gets the value of its
// thread-specific s_servicesKey then create the Services object and set the
// key to point to it
......@@ -113,7 +88,7 @@ castor::Services* castor::BaseObject::services()
throw e;
}
}
return services;
}
......
......@@ -75,14 +75,6 @@ namespace castor {
*/
Services* svcs() throw(castor::exception::Exception);
private:
/**
* small function that creates a thread-specific storage key
* for the services
*/
static void makeServicesKey() throw (castor::exception::Exception);
protected:
/**
......@@ -91,17 +83,32 @@ namespace castor {
static Services* s_sharedServices;
private:
/**
* The key to thread-specific storage for Services
* A little class that will construct the pthread key at init time
*/
static pthread_key_t s_servicesKey;
class pthreadKey {
public:
pthreadKey() throw (castor::exception::Exception) {
int rc = pthread_key_create(&m_key, NULL);
if (rc != 0) {
castor::exception::Exception e(rc);
e.getMessage() << "Error caught in call to pthread_key_create (from castor::BaseObject::pthreadKey::pthreadKey";
throw e;
}
}
operator pthread_key_t () const {
return m_key;
}
private:
pthread_key_t m_key;
};
/**
* The key for creating only once the thread-specific storage key for services
* The key to thread-specific storage for Services
*/
static pthread_once_t s_servicesOnce;
static pthreadKey s_servicesKey;
}; // end of class BaseObject
} // end of namespace castor
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment