Browse Source

wait twister threads to finish before destroying libtorrent session object.

may fix #200.
miguelfreitas
Miguel Freitas 11 years ago
parent
commit
8f03692074
  1. 59
      src/twister.cpp

59
src/twister.cpp

@ -43,6 +43,7 @@ twister::twister()
using namespace libtorrent; using namespace libtorrent;
static session *ses = NULL; static session *ses = NULL;
static bool m_shuttingDownSession = false;
static bool m_usingProxy; static bool m_usingProxy;
static int num_outstanding_resume_data; static int num_outstanding_resume_data;
@ -55,6 +56,7 @@ enum ExpireResType { SimpleNoExpire, NumberedNoExpire, PostNoExpireRecent };
static map<std::string, ExpireResType> m_noExpireResources; static map<std::string, ExpireResType> m_noExpireResources;
static map<std::string, torrent_handle> m_userTorrent; static map<std::string, torrent_handle> m_userTorrent;
static boost::scoped_ptr<CLevelDB> m_swarmDb; static boost::scoped_ptr<CLevelDB> m_swarmDb;
static int m_threadsToJoin;
static CCriticalSection cs_spamMsg; static CCriticalSection cs_spamMsg;
static std::string m_preferredSpamLang = "[en]"; static std::string m_preferredSpamLang = "[en]";
@ -66,6 +68,25 @@ static std::map<std::string,UserData> m_users;
static CCriticalSection cs_seenHashtags; static CCriticalSection cs_seenHashtags;
static std::map<std::string,double> m_seenHashtags; static std::map<std::string,double> m_seenHashtags;
class SimpleThreadCounter {
public:
SimpleThreadCounter(CCriticalSection *lock, int *counter, const char *name) :
m_lock(lock), m_counter(counter), m_name(name) {
RenameThread(m_name);
LOCK(*m_lock);
(*m_counter)++;
}
~SimpleThreadCounter() {
printf("%s thread exit\n", m_name);
LOCK(*m_lock);
(*m_counter)--;
}
private:
CCriticalSection *m_lock;
int *m_counter;
const char *m_name;
};
#define USER_DATA_FILE "user_data" #define USER_DATA_FILE "user_data"
#define GLOBAL_DATA_FILE "global_data" #define GLOBAL_DATA_FILE "global_data"
@ -84,7 +105,7 @@ sha1_hash dhtTargetHash(std::string const &username, std::string const &resource
torrent_handle startTorrentUser(std::string const &username, bool following) torrent_handle startTorrentUser(std::string const &username, bool following)
{ {
bool userInTxDb = usernameExists(username); // keep this outside cs_twister to avoid deadlock bool userInTxDb = usernameExists(username); // keep this outside cs_twister to avoid deadlock
if( !userInTxDb ) if( !userInTxDb || !ses)
return torrent_handle(); return torrent_handle();
LOCK(cs_twister); LOCK(cs_twister);
@ -205,10 +226,9 @@ data_error:
return -2; return -2;
} }
void ThreadWaitExtIP() void ThreadWaitExtIP()
{ {
RenameThread("wait-extip"); SimpleThreadCounter threadCounter(&cs_twister, &m_threadsToJoin, "wait-extip");
std::string ipStr; std::string ipStr;
@ -418,16 +438,16 @@ int getDhtNodes(boost::int64_t *dht_global_nodes)
void ThreadMaintainDHTNodes() void ThreadMaintainDHTNodes()
{ {
RenameThread("maintain-dht-nodes"); SimpleThreadCounter threadCounter(&cs_twister, &m_threadsToJoin, "maintain-dht-nodes");
while(!ses) { while(!ses && !m_shuttingDownSession) {
MilliSleep(200); MilliSleep(200);
} }
int64 lastSaveResumeTime = GetTime(); int64 lastSaveResumeTime = GetTime();
int lastTotalNodesCandidates = 0; int lastTotalNodesCandidates = 0;
while(1) { while(ses && !m_shuttingDownSession) {
session_status ss = ses->status(); session_status ss = ses->status();
int dht_nodes = ss.dht_nodes; int dht_nodes = ss.dht_nodes;
bool nodesAdded = false; bool nodesAdded = false;
@ -535,11 +555,14 @@ void ThreadSessionAlerts()
static map<sha1_hash, bool> neighborCheck; static map<sha1_hash, bool> neighborCheck;
static map<sha1_hash, int64_t> statusCheck; static map<sha1_hash, int64_t> statusCheck;
while(!ses) { SimpleThreadCounter threadCounter(&cs_twister, &m_threadsToJoin, "session-alerts");
while(!ses && !m_shuttingDownSession) {
MilliSleep(200); MilliSleep(200);
} }
while (ses) { while (ses && !m_shuttingDownSession) {
alert const* a = ses->wait_for_alert(seconds(10)); alert const* a = ses->wait_for_alert(seconds(1));
if (a == 0) continue; if (a == 0) continue;
std::deque<alert*> alerts; std::deque<alert*> alerts;
@ -721,6 +744,7 @@ void startSessionTorrent(boost::thread_group& threadGroup)
m_noExpireResources["status"] = SimpleNoExpire; m_noExpireResources["status"] = SimpleNoExpire;
m_noExpireResources["post"] = PostNoExpireRecent; m_noExpireResources["post"] = PostNoExpireRecent;
m_threadsToJoin = 0;
threadGroup.create_thread(boost::bind(&ThreadWaitExtIP)); threadGroup.create_thread(boost::bind(&ThreadWaitExtIP));
threadGroup.create_thread(boost::bind(&ThreadMaintainDHTNodes)); threadGroup.create_thread(boost::bind(&ThreadMaintainDHTNodes));
threadGroup.create_thread(boost::bind(&ThreadSessionAlerts)); threadGroup.create_thread(boost::bind(&ThreadSessionAlerts));
@ -739,6 +763,17 @@ void stopSessionTorrent()
MilliSleep(100); MilliSleep(100);
} }
m_shuttingDownSession = true;
int threadsToJoin = 0;
do {
MilliSleep(100);
LOCK(cs_twister);
if( threadsToJoin != m_threadsToJoin ) {
threadsToJoin = m_threadsToJoin;
printf("twister threads to join = %d\n", threadsToJoin);
}
} while( threadsToJoin );
printf("\nsaving session state\n"); printf("\nsaving session state\n");
entry session_state; entry session_state;
@ -755,6 +790,8 @@ void stopSessionTorrent()
boost::filesystem::path sesStatePath = GetDataDir() / "ses_state"; boost::filesystem::path sesStatePath = GetDataDir() / "ses_state";
save_file(sesStatePath.string(), out); save_file(sesStatePath.string(), out);
ses->stop_dht();
delete ses; delete ses;
ses = NULL; ses = NULL;
} }
@ -2093,7 +2130,7 @@ Value torrentstatus(const Array& params, bool fHelp)
result.push_back(Pair("num_complete", status.num_complete)); result.push_back(Pair("num_complete", status.num_complete));
result.push_back(Pair("num_pieces", status.num_pieces)); result.push_back(Pair("num_pieces", status.num_pieces));
string bitfield; string bitfield;
for(int i = 0; i < status.pieces.size(); i++) { for(std::size_t i = 0; i < status.pieces.size(); i++) {
bitfield.append( status.pieces[i]?"1":"0" ); bitfield.append( status.pieces[i]?"1":"0" );
} }
result.push_back(Pair("bitfield", bitfield)); result.push_back(Pair("bitfield", bitfield));
@ -2115,7 +2152,7 @@ Value torrentstatus(const Array& params, bool fHelp)
info.push_back(Pair("download_queue_length", p.download_queue_length)); info.push_back(Pair("download_queue_length", p.download_queue_length));
info.push_back(Pair("failcount", p.failcount)); info.push_back(Pair("failcount", p.failcount));
bitfield = ""; bitfield = "";
for(int i = 0; i < p.pieces.size(); i++) { for(std::size_t i = 0; i < p.pieces.size(); i++) {
bitfield.append( p.pieces[i]?"1":"0" ); bitfield.append( p.pieces[i]?"1":"0" );
} }
info.push_back(Pair("bitfield", bitfield)); info.push_back(Pair("bitfield", bitfield));

Loading…
Cancel
Save