私は作業中のC ++デーモンを持っています。問題は、デーモンが月に 1 ~ 2 回クラッシュすることです。以下の GDB 出力からわかるように、デーモンがunsigned int
コンテナーでセッション ID を検索するときに発生しますstd::map <unsigned int const, SessionID*>
。私は問題を再現できず、おそらくユーザーからのデータに問題があると思います (std::sting cookie_ssid
予期しないデータがあり、変換後にstrtoul
何か問題が発生している可能性があります) (これは正しい取得方法ではないことを知っておいunsigned int
てください) 。
.core
デーモンがクラッシュした後、ファイルしかありません。でその問題を参照してくださいif (!_M_impl._M_key_compare(_S_key(__x), __k))
。この問題を解決する方法はありますか? どうもありがとう。
GDB 出力:
#0 std::_Rb_tree<unsigned int, std::pair<unsigned int const, SessionID*>, std::_Select1st<std::pair<unsigned int const, SessionID*> >, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, SessionID*> > >::find (this=0x529df15c, __k=@0x7f5fab7c)
at stl_tree.h:1376
##########
1376 if (!_M_impl._M_key_compare(_S_key(__x), __k))
##########
#0 std::_Rb_tree<unsigned int, std::pair<unsigned int const, SessionID*>, std::_Select1st<std::pair<unsigned int const, SessionID*> >, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, SessionID*> > >::find (
this=0x529df15c, __k=@0x7f5fab7c) at stl_tree.h:1376
#1 0x0805e6be in TR::find_session (this=0x529df110,
cookie_ssid=@0x47ef3614, ptr_to_ptr_session=0x7f5fac7c)
at stl_map.h:542
関数TR::find_session
は次のようにリリースされます。
bool TR::find_session ( const std::string &cookie_ssid, SessionID **ptr_to_ptr_session )
{
unsigned int uint_sessionid = std::strtoul ( cookie_ssid.c_str(),NULL,0);
MUTEX_map_sessionids.lock_reading();
std::map<unsigned int, SessionID*>::iterator it_sessionids = map_sessionids.find( uint_sessionid );
if ( it_sessionids != map_sessionids.end() )
{ // exists
*ptr_to_ptr_session = it_sessionids->second;
MUTEX_map_sessionids.unlock();
return true;
}
MUTEX_map_sessionids.unlock();
return false;
}
EDIT 別のスレッドで動作するクリーンアップ機能 (1 分または 5 分に 1 回)。コメントで要求されたとおりです。この機能についてはよくわかりません。多分そのバギー....
void TR::cleanup_sessions () // not protected from multithread using! used only at one thread
{
std::list<SessionID*> list_to_clean; // tmplary store sessions to delete
MUTEX_map_sessionids.lock_reading();
std::map<unsigned int, SessionID*>::iterator it_sessionids = map_sessionids.begin();
MUTEX_map_sessionids.unlock();
while ( true )
{
MUTEX_map_sessionids.lock_writing();
if (it_sessionids == map_sessionids.end() )
{
MUTEX_map_sessionids.unlock();
break;
}
SessionID *ptr_sessionid = it_sessionids->second;
time_t secondsnow = time (NULL);
ptr_sessionid->MUTEX_all_session.lock_reading();
time_t lastaccesstime = ptr_sessionid->last_access_time;
size_t total_showed = ptr_sessionid->map_showed.size();
ptr_sessionid->MUTEX_all_session.unlock();
if ( lastaccesstime and secondsnow - lastaccesstime > LOCALSESSION_LIFETIME_SEC ) // lifetime end!
{
// delete session from map
map_sessionids.erase( it_sessionids++ ); // Increments the iterator but returns the original value for use by erase
MUTEX_map_sessionids.unlock();
list_to_clean.push_back ( ptr_sessionid ); // at the end
}
else if ( total_showed == 0 and secondsnow - lastaccesstime > 36000 ) // not active for N secontes
{
map_sessionids.erase( it_sessionids++ ); // Increments the iterator but returns the original value for use by erase
MUTEX_map_sessionids.unlock();
// add pointer to list to delete it latter
list_to_clean.push_back ( ptr_sessionid ); // at the end
}
else
{
++it_sessionids; // next
MUTEX_map_sessionids.unlock();
}
}
// used? pause
if ( !list_to_clean.empty() )
{
//sleep(1);
}
// cleanup session deleted from working map
while ( !list_to_clean.empty() )
{
SessionID *ptr_sessionid_to_delete = list_to_clean.front();
list_to_clean.pop_front();
ptr_sessionid_to_delete->MUTEX_all_session.lock_writing(); // protected lock session mutex. can not delete session if its already locked. (additational protection)
ptr_sessionid_to_delete->cleanup();
delete ptr_sessionid_to_delete;
}
}
繰り返しごとにわかるように、map_sessions をロック/ロック解除します。これは、この時点で他のスレッドが新しいセッションとそのクリティカルを検索/挿入するためです。これは、ユーザーが待機できないためです。