Fix a segfault when aborting a download

This commit is contained in:
Learath Lea 2015-01-28 14:13:56 +02:00
parent 2d61e7610e
commit ace7e8208a
3 changed files with 22 additions and 6 deletions

View file

@ -310,6 +310,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
// map download // map download
m_aMapdownloadFilename[0] = 0; m_aMapdownloadFilename[0] = 0;
m_aMapdownloadName[0] = 0; m_aMapdownloadName[0] = 0;
m_pMapdownloadTask = 0;
m_MapdownloadFile = 0; m_MapdownloadFile = 0;
m_MapdownloadChunk = 0; m_MapdownloadChunk = 0;
m_MapdownloadCrc = 0; m_MapdownloadCrc = 0;
@ -735,6 +736,8 @@ void CClient::DisconnectWithReason(const char *pReason)
// disable all downloads // disable all downloads
m_MapdownloadChunk = 0; m_MapdownloadChunk = 0;
if(m_pMapdownloadTask)
m_pMapdownloadTask->Abort();
if(m_MapdownloadFile) if(m_MapdownloadFile)
io_close(m_MapdownloadFile); io_close(m_MapdownloadFile);
m_MapdownloadFile = 0; m_MapdownloadFile = 0;
@ -2420,14 +2423,21 @@ void CClient::Update()
// pump the network // pump the network
PumpNetwork(); PumpNetwork();
if(m_pMapdownloadTask){ if(m_pMapdownloadTask)
{
if(m_pMapdownloadTask->State() == CFetchTask::STATE_DONE) if(m_pMapdownloadTask->State() == CFetchTask::STATE_DONE)
FinishMapDownload(); FinishMapDownload();
else if(m_pMapdownloadTask->State() == CFetchTask::STATE_ERROR){ else if(m_pMapdownloadTask->State() == CFetchTask::STATE_ERROR)
{
dbg_msg("webdl", "HTTP failed falling back to gameserver."); dbg_msg("webdl", "HTTP failed falling back to gameserver.");
ResetMapDownload(); ResetMapDownload();
SendMapRequest(); SendMapRequest();
} }
else if(m_pMapdownloadTask->State() == CFetchTask::STATE_ABORTED)
{
delete m_pMapdownloadTask;
m_pMapdownloadTask = 0;
}
} }

View file

@ -40,6 +40,7 @@ void CFetcher::QueueAdd(CFetchTask *pTask, const char *pUrl, const char *pDest,
pTask->m_pfnCompCallback = pfnCompCb; pTask->m_pfnCompCallback = pfnCompCb;
pTask->m_pUser = pUser; pTask->m_pUser = pUser;
pTask->m_Size = pTask->m_Progress = 0; pTask->m_Size = pTask->m_Progress = 0;
pTask->m_Abort = false;
lock_wait(m_Lock); lock_wait(m_Lock);
if(!m_pFirst) if(!m_pFirst)
@ -122,10 +123,11 @@ bool CFetcher::FetchFile(CFetchTask *pTask)
dbg_msg("fetcher", "Downloading %s", pTask->m_pDest); dbg_msg("fetcher", "Downloading %s", pTask->m_pDest);
pTask->m_State = CFetchTask::STATE_RUNNING; pTask->m_State = CFetchTask::STATE_RUNNING;
if(curl_easy_perform(m_pHandle) != CURLE_OK) int ret = curl_easy_perform(m_pHandle);
if(ret != CURLE_OK)
{ {
dbg_msg("fetcher", "Task failed. libcurl error: %s", aErr); dbg_msg("fetcher", "Task failed. libcurl error: %s", aErr);
pTask->m_State = CFetchTask::STATE_ERROR; pTask->m_State = (ret == CURLE_ABORTED_BY_CALLBACK) ? CFetchTask::STATE_ABORTED : CFetchTask::STATE_ERROR;
return false; return false;
} }
io_close(File); io_close(File);
@ -150,5 +152,5 @@ int CFetcher::ProgressCallback(void *pUser, double DlTotal, double DlCurr, doubl
pTask->m_Progress = (100 * DlCurr) / (DlTotal ? DlTotal : 1); pTask->m_Progress = (100 * DlCurr) / (DlTotal ? DlTotal : 1);
if(pTask->m_pfnProgressCallback) if(pTask->m_pfnProgressCallback)
pTask->m_pfnProgressCallback(pTask, pTask->m_pUser); pTask->m_pfnProgressCallback(pTask, pTask->m_pUser);
return 0; return pTask->m_Abort ? -1 : 0;
} }

View file

@ -25,6 +25,7 @@ class CFetchTask
double m_Size; double m_Size;
int m_Progress; int m_Progress;
int m_State; int m_State;
bool m_Abort;
public: public:
CFetchTask(); CFetchTask();
@ -34,6 +35,7 @@ public:
STATE_QUEUED, STATE_QUEUED,
STATE_RUNNING, STATE_RUNNING,
STATE_DONE, STATE_DONE,
STATE_ABORTED,
}; };
const double Current() const { return m_Current; }; const double Current() const { return m_Current; };
@ -41,6 +43,8 @@ public:
const int Progress() const { return m_Progress; }; const int Progress() const { return m_Progress; };
const int State() const { return m_State; }; const int State() const { return m_State; };
const char *Dest() const { return m_pDest; }; const char *Dest() const { return m_pDest; };
void Abort() { m_Abort = true; };
}; };
class IFetcher : public IInterface class IFetcher : public IInterface