STK would hang if the user quits before the network_http object

was fully initialised (the separate thread did not test for
m_command==HC_QUIT before the cond_wait, and if the signal had
already been sent, the thread would not come back from the wait,
causing STK to hang).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7532 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-01-24 22:51:58 +00:00
parent 7f6b0412ee
commit e4b86ffc5d

View File

@ -59,6 +59,9 @@ NetworkHttp::NetworkHttp() : m_news(""), m_progress(-1.0f), m_abort(false)
pthread_mutex_init(&m_mutex_command, NULL);
pthread_cond_init(&m_cond_command, NULL);
// Since there are no threads at this stage, just init
// m_command without mutex.
m_command = HC_SLEEP;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@ -101,9 +104,17 @@ void *NetworkHttp::mainLoop(void *obj)
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
// Wait in the main loop till a command is received
// (atm only QUIT is used).
pthread_mutex_lock(&me->m_mutex_command);
me->m_command = HC_SLEEP;
// Handle the case that STK is cancelled before the while loop
// is entered. If this would happen, this thread hangs in
// pthread_cond_wait (since cond_signal was done before the wait),
// and stk hangs since the thread can't join.
if(me->m_command==HC_QUIT)
{
return NULL;
}
while(1)
{
pthread_cond_wait(&me->m_cond_command, &me->m_mutex_command);
@ -113,7 +124,7 @@ void *NetworkHttp::mainLoop(void *obj)
pthread_exit(NULL);
break;
case HC_SLEEP:
case HC_INIT:
case HC_INIT:
break;
case HC_NEWS:
assert(false);
@ -223,25 +234,25 @@ size_t NetworkHttp::writeStr(char ptr [], size_t size, size_t nb_char,
std::string NetworkHttp::downloadToStrInternal(std::string url)
{
m_abort.set(false);
CURL *session = curl_easy_init();
CURL *session = curl_easy_init();
std::string full_url = (std::string)UserConfigParams::m_server_addons
+ "/" + url;
curl_easy_setopt(session, CURLOPT_URL, full_url.c_str());
std::string fout;
//from and out
curl_easy_setopt(session, CURLOPT_WRITEDATA, &fout );
curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, &NetworkHttp::writeStr);
int success = curl_easy_perform(session);
//stop curl
curl_easy_cleanup(session);
if (success == 0) return fout;
else return "";
curl_easy_setopt(session, CURLOPT_URL, full_url.c_str());
std::string fout;
//from and out
curl_easy_setopt(session, CURLOPT_WRITEDATA, &fout );
curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, &NetworkHttp::writeStr);
int success = curl_easy_perform(session);
//stop curl
curl_easy_cleanup(session);
if (success == 0) return fout;
else return "";
} // downloadToStrInternal
// ----------------------------------------------------------------------------
@ -255,17 +266,17 @@ bool NetworkHttp::downloadFileInternal(const std::string &file,
{
if(UserConfigParams::m_verbosity>=3)
printf("[addons] Downloading %s\n", file.c_str());
CURL *session = curl_easy_init();
CURL *session = curl_easy_init();
std::string full_url = (std::string)UserConfigParams::m_server_addons
+ "/" + file;
curl_easy_setopt(session, CURLOPT_URL, full_url.c_str());
curl_easy_setopt(session, CURLOPT_URL, full_url.c_str());
FILE * fout = fopen(file_manager->getAddonsFile(save_filename).c_str(),
"wb");
//from and out
curl_easy_setopt(session, CURLOPT_WRITEDATA, fout );
curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, fwrite);
//from and out
curl_easy_setopt(session, CURLOPT_WRITEDATA, fout );
curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, fwrite);
if(is_asynchron)
{
curl_easy_setopt(session, CURLOPT_PROGRESSFUNCTION,
@ -273,14 +284,14 @@ bool NetworkHttp::downloadFileInternal(const std::string &file,
// Necessary, oyherwise the progress function doesn't work
curl_easy_setopt(session, CURLOPT_NOPROGRESS, 0);
}
int success = curl_easy_perform(session);
//close the file where we downloaded the content
fclose(fout);
//stop curl
curl_easy_cleanup(session);
int success = curl_easy_perform(session);
//close the file where we downloaded the content
fclose(fout);
//stop curl
curl_easy_cleanup(session);
if(is_asynchron)
m_progress.set( (success==CURLE_OK) ? 1.0f : -1.0f );