From: <av...@us...> - 2011-06-03 06:29:09
|
Revision: 7321 http://openhpi.svn.sourceforge.net/openhpi/?rev=7321&view=rev Author: avpak Date: 2011-06-03 06:29:03 +0000 (Fri, 03 Jun 2011) Log Message: ----------- Fix for #3310802 Modified Paths: -------------- openhpi/trunk/baselib/session.cpp Modified: openhpi/trunk/baselib/session.cpp =================================================================== --- openhpi/trunk/baselib/session.cpp 2011-06-02 10:28:26 UTC (rev 7320) +++ openhpi/trunk/baselib/session.cpp 2011-06-03 06:29:03 UTC (rev 7321) @@ -42,11 +42,36 @@ explicit cSession(); ~cSession(); + void Ref() + { + ++m_ref_cnt; + } + + void Unref() + { + --m_ref_cnt; + } + + int GetRefCnf() const + { + return m_ref_cnt; + } + SaHpiDomainIdT GetDomainId() const { return m_did; } + SaHpiSessionIdT GetSid() const + { + return m_sid; + } + + void SetSid( SaHpiSessionIdT sid ) + { + m_sid = sid; + } + SaErrorT GetEntityRoot( SaHpiEntityPathT& entity_root ) const; SaErrorT RpcOpen( SaHpiDomainIdT did ); @@ -73,14 +98,18 @@ static const gulong NEXT_RPC_ATTEMPT_TIMEOUT = 2 * G_USEC_PER_SEC; // data + volatile int m_ref_cnt; SaHpiDomainIdT m_did; + SaHpiSessionIdT m_sid; SaHpiSessionIdT m_remote_sid; GStaticPrivate m_sockets; }; cSession::cSession() - : m_did( SAHPI_UNSPECIFIED_DOMAIN_ID ), + : m_ref_cnt( 0 ), + m_did( SAHPI_UNSPECIFIED_DOMAIN_ID ), + m_sid( 0 ), m_remote_sid( 0 ) { g_static_private_init( &m_sockets ); @@ -250,52 +279,65 @@ ohc_unlock(); } -static cSession * sessions_get( SaHpiSessionIdT sid ) +static SaHpiSessionIdT sessions_add( cSession * session ) { + static SaHpiSessionIdT next_sid = 1; + ohc_lock(); + SaHpiSessionIdT sid = next_sid; + ++next_sid; + session->SetSid( sid ); + g_hash_table_insert( sessions, sid_key( sid ), session ); + ohc_unlock(); + + return sid; +} + +static cSession * sessions_get_ref( SaHpiSessionIdT sid ) +{ + ohc_lock(); gpointer value = g_hash_table_lookup( sessions, sid_key( sid ) ); + cSession * session = reinterpret_cast<cSession*>(value); + if ( session ) { + session->Ref(); + } ohc_unlock(); - return reinterpret_cast<cSession*>(value); + return session; } -gboolean dehash_sessions( gpointer /* key */, gpointer value, gpointer user_data ) +static void dehash_func( gpointer /* key */, gpointer value, gpointer user_data ) { GList ** pvalues = reinterpret_cast<GList **>(user_data); + cSession * session = reinterpret_cast<cSession*>(value); + session->Ref(); *pvalues = g_list_append( *pvalues, value ); - return TRUE; } -static GList * sessions_take_all() +static GList * sessions_get_ref_all() { ohc_lock(); GList * sessions_list = 0; - g_hash_table_foreach_remove( sessions, dehash_sessions, &sessions_list ); + g_hash_table_foreach( sessions, dehash_func, &sessions_list ); ohc_unlock(); return sessions_list; } -static SaHpiSessionIdT sessions_add( cSession * session ) +static void sessions_unref( cSession * session, bool closed = false ) { - static SaHpiSessionIdT next_sid = 1; - ohc_lock(); - SaHpiSessionIdT sid = next_sid; - ++next_sid; - g_hash_table_insert( sessions, sid_key( sid ), session ); + session->Unref(); + if ( closed ) { + session->Unref(); + g_hash_table_remove( sessions, sid_key( session->GetSid() ) ); + } + if ( session->GetRefCnf() < 0 ) { + delete session; + } ohc_unlock(); - - return sid; } -static void sessions_remove( SaHpiSessionIdT sid ) -{ - ohc_lock(); - g_hash_table_remove( sessions, sid_key( sid ) ); - ohc_unlock(); -} - /*************************************************************** * Session Layer: Interface **************************************************************/ @@ -322,27 +364,22 @@ SaErrorT ohc_sess_close( SaHpiSessionIdT sid ) { - // TODO fix race condition - cSession * session = sessions_get( sid ); + cSession * session = sessions_get_ref( sid ); if ( !session ) { return SA_ERR_HPI_INVALID_SESSION; } SaErrorT rv = session->RpcClose(); - if ( rv == SA_OK ) { - sessions_remove( sid ); - delete session; - } + sessions_unref( session, ( rv == SA_OK ) ); return rv; } SaErrorT ohc_sess_close_all() { - // TODO fix race condition SaErrorT rv = SA_OK; - GList * sessions_list = sessions_take_all(); + GList * sessions_list = sessions_get_ref_all(); if ( g_list_length( sessions_list ) == 0 ) { //rv = SA_ERR_HPI_INVALID_REQUEST; rv = SA_OK; @@ -351,7 +388,7 @@ while ( item ) { cSession * session = reinterpret_cast<cSession*>(item->data); session->RpcClose(); - delete session; + sessions_unref( session, true ); item = item->next; } } @@ -367,36 +404,40 @@ ClientRpcParams& iparams, ClientRpcParams& oparams ) { - // TODO fix race condition - cSession * session = sessions_get( sid ); + cSession * session = sessions_get_ref( sid ); if ( !session ) { return SA_ERR_HPI_INVALID_SESSION; } - return session->Rpc( id, iparams, oparams ); + SaErrorT rv = session->Rpc( id, iparams, oparams ); + sessions_unref( session ); + + return rv; } SaErrorT ohc_sess_get_did( SaHpiSessionIdT sid, SaHpiDomainIdT& did ) { - // TODO fix race condition - cSession * session = sessions_get( sid ); + cSession * session = sessions_get_ref( sid ); if ( !session ) { return SA_ERR_HPI_INVALID_SESSION; } did = session->GetDomainId(); + sessions_unref( session ); return SA_OK; } SaErrorT ohc_sess_get_entity_root( SaHpiSessionIdT sid, SaHpiEntityPathT& ep ) { - // TODO fix race condition - cSession * session = sessions_get( sid ); + cSession * session = sessions_get_ref( sid ); if ( !session ) { return SA_ERR_HPI_INVALID_SESSION; } - return session->GetEntityRoot( ep ); + SaErrorT rv = session->GetEntityRoot( ep ); + sessions_unref( session ); + + return rv; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |