Added proper aborting of curl download threads.

Print warning and progress reports only with
verbosity 3 or above, all addons messages now
start with [addons].


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7503 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-01-23 04:24:55 +00:00
parent d8b04b2338
commit 6eddb2baf9
6 changed files with 57 additions and 19 deletions

View File

@ -104,7 +104,7 @@ void AddonsManager::initOnline(const XMLNode *xml)
if(file_manager->fileExists(full_path))
{
if(UserConfigParams::m_verbosity>=3)
printf("Removing cached icon '%s'.\n",
printf("[addons] Removing cached icon '%s'.\n",
addon.getIconBasename().c_str());
file_manager->removeFile(full_path);
}
@ -124,9 +124,9 @@ void AddonsManager::initOnline(const XMLNode *xml)
else
{
fprintf(stderr,
"Found invalid node '%s' while downloading addons.\n",
"[addons] Found invalid node '%s' while downloading addons.\n",
node->getName().c_str());
fprintf(stderr, "Ignored.\n");
fprintf(stderr, "[addons] Ignored.\n");
}
} // for i<xml->getNumNodes
delete xml;
@ -205,7 +205,7 @@ void *AddonsManager::downloadIcons(void *obj)
for(unsigned int i=0; i<me->m_addons_list.getData().size(); i++)
{
if(!me->m_addons_list.getData()[i].iconReady())
printf("No icon for '%s'.\n",
printf("[addons] No icon for '%s'.\n",
me->m_addons_list.getData()[i].getId().c_str());
}
me->saveInstalled();
@ -230,7 +230,7 @@ bool AddonsManager::onlineReady()
void AddonsManager::loadInstalledAddons()
{
/* checking for installed addons */
std::cout << "[Addons] Loading an xml file for installed addons: ";
std::cout << "[addons] Loading an xml file for installed addons: ";
std::cout << m_file_installed << std::endl;
const XMLNode *xml = file_manager->createXMLTree(m_file_installed);
if(!xml)

View File

@ -54,7 +54,7 @@ NetworkHttp *network_http;
* This separate thread is running in NetworkHttp::mainLoop, and is being
* waken up if a command is issued (e.g. using downloadFileAsynchronous).
*/
NetworkHttp::NetworkHttp() : m_news(""), m_progress(-1.0f)
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);
@ -133,15 +133,24 @@ void *NetworkHttp::mainLoop(void *obj)
*/
NetworkHttp::~NetworkHttp()
{
// if a download should be active (which means it was cancelled by the
// user, in which case it will still be ongoing in the background)
// we can't get the mutex, and would have to wait for a timeout,
// and we couldn't finish STK. This way we request an abort of
// a download, which mean we can get the mutex and ask the service
// thread here to cancel properly.
cancelDownload();
pthread_mutex_lock(&m_mutex_command);
{
m_command=HC_QUIT;
pthread_cond_signal(&m_cond_command);
}
pthread_mutex_unlock(&m_mutex_command);
printf("[addons] Mutex unlocked.\n");
void *result;
pthread_join(m_thread_id, &result);
printf("[addons] Network thread joined.\n");
pthread_mutex_destroy(&m_mutex_command);
pthread_cond_destroy(&m_cond_command);
@ -213,6 +222,7 @@ 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();
std::string full_url = (std::string)UserConfigParams::m_server_addons
@ -244,7 +254,7 @@ bool NetworkHttp::downloadFileInternal(const std::string &file,
bool is_asynchron)
{
if(UserConfigParams::m_verbosity>=3)
printf("Downloading %s\n", file.c_str());
printf("[addons] Downloading %s\n", file.c_str());
CURL *session = curl_easy_init();
std::string full_url = (std::string)UserConfigParams::m_server_addons
+ "/" + file;
@ -277,6 +287,18 @@ bool NetworkHttp::downloadFileInternal(const std::string &file,
return success==CURLE_OK;
} // downloadFileInternal
// ----------------------------------------------------------------------------
/** Signals to the progress function to request any ongoing download to be
* cancelled. This function can also be called if there is actually no
* download atm. The function progressDownload checks m_abort and will
* return a non-zero value which causes libcurl to abort. */
void NetworkHttp::cancelDownload()
{
if(UserConfigParams::m_verbosity>=3)
printf("[addons] Requesting cancellation of download.\n");
m_abort.set(true);
} // cancelDownload
// ----------------------------------------------------------------------------
/** External interface to download a file synchronously, i.e. it will only
* return once the download is complete.
@ -288,6 +310,9 @@ bool NetworkHttp::downloadFileSynchron(const std::string &file,
const std::string &save)
{
const std::string &save_filename = (save!="") ? save : file;
if(UserConfigParams::m_verbosity>=3)
printf("[addons] Download synchron '%s' as '%s'.\n",
file.c_str(), save_filename.c_str());
return downloadFileInternal(file, save_filename,
/*is_asynchron*/false);
@ -308,6 +333,9 @@ void NetworkHttp::downloadFileAsynchron(const std::string &file,
m_file = file;
m_save_filename = (save!="") ? save : file;
if(UserConfigParams::m_verbosity>=3)
printf("[addons] Download asynchron '%s' as '%s'.\n",
file.c_str(), m_save_filename.c_str());
// Wake up the network http thread
pthread_mutex_lock(&m_mutex_command);
{
@ -329,6 +357,14 @@ int NetworkHttp::progressDownload(void *clientp,
double download_total, double download_now,
double upload_total, double upload_now)
{
// Check if we are asked to abort the download. If so, signal this
// back to libcurl by returning a non-zero status.
if(network_http->m_abort.get())
{
if(UserConfigParams::m_verbosity>=3)
printf("[addons] Aborting download in progress.\n");
return 1;
}
float f;
if(download_now < download_total)
{

View File

@ -64,6 +64,9 @@ private:
* this value only becomes 1.0f, if the download is completed.*/
Synchronised<float> m_progress;
/** Signal an abort in case that a download is still happening. */
Synchronised<bool> m_abort;
/** Thread id of the thread running in this object. */
pthread_t m_thread_id;
@ -91,7 +94,7 @@ public:
const std::string
getNewsMessage() const;
float getProgress() const;
void cancelDownload();
}; // NetworkHttp
extern NetworkHttp *network_http;

View File

@ -75,7 +75,7 @@ bool extract_zip(const std::string &from, const std::string &to)
for(unsigned int i=0; i<zip_file_list->getFileCount(); i++)
{
const std::string current_file=zip_file_list->getFileName(i).c_str();
std::cout << current_file << std::endl;
printf("[addons] Unzipping file '%s'.\n", current_file.c_str());
if(zip_file_list->isDirectory(i)) continue;
if(current_file[0]=='.') continue;
const std::string base = StringUtils::getBasename(current_file);
@ -84,8 +84,8 @@ bool extract_zip(const std::string &from, const std::string &to)
file_system->createAndOpenFile(current_file.c_str());
if(!src_file)
{
printf("Can't read file '%s'.\n", current_file.c_str());
printf("This is ignored, but the addon might not work.\n");
printf("[addons] Can't read file '%s'.\n", current_file.c_str());
printf("[addons] This is ignored, but the addon might not work.\n");
error = true;
continue;
}
@ -94,19 +94,19 @@ bool extract_zip(const std::string &from, const std::string &to)
file_system->createAndWriteFile((to+"/"+base).c_str());
if(dst_file == NULL)
{
printf("Couldn't create the file '%s'.\n",
printf("[addons] Couldn't create the file '%s'.\n",
(to+"/"+current_file).c_str());
printf("The directory might not exist.\n");
printf("This is ignored, but the addon might not work.\n");
printf("[addons] The directory might not exist.\n");
printf("[addons] This is ignored, but the addon might not work.\n");
error = true;
continue;
}
if (IFileSystem_copyFileToFile(dst_file, src_file) < 0)
{
printf("Could not copy '%s' from archive '%s'.\n",
printf("[addons] Could not copy '%s' from archive '%s'.\n",
current_file.c_str(), from.c_str());
printf("This is ignored, but the addon might not work.\n");
printf("[addons] This is ignored, but the addon might not work.\n");
error = true;
}
dst_file->drop();

View File

@ -64,13 +64,11 @@ void AddonsScreen::init()
Screen::init();
getWidget<GUIEngine::RibbonWidget>("category")->setDeactivated();
std::cout << "[Addons] Using directory <" + file_manager->getAddonsDir()
std::cout << "[addons] Using directory <" + file_manager->getAddonsDir()
<< ">\n";
GUIEngine::ListWidget* w_list =
getWidget<GUIEngine::ListWidget>("list_addons");
w_list->setIcons(m_icon_bank);
//w_list->clear();
std::cout << "icon bank" << std::endl;
getWidget<GUIEngine::LabelWidget>("update_status")
->setText(_("Updating the list..."));

View File

@ -83,6 +83,7 @@ GUIEngine::EventPropagation
{
if(event_source == "cancel")
{
network_http->cancelDownload();
dismiss();
return GUIEngine::EVENT_BLOCK;
}