1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-17 00:44:19 +00:00

Fixed a race condition in iOS DownloadTask implementation

This commit is contained in:
hogliux 2016-11-24 15:00:51 +00:00
parent 119640f55f
commit da5805fb48

View file

@ -385,7 +385,7 @@ struct BackgroundDownloadTask : public URL::DownloadTask
URL::DownloadTask::Listener* listenerToUse)
: targetLocation (targetLocationToUse), listener (listenerToUse),
delegate (nullptr), session (nullptr), downloadTask (nullptr),
connectFinished (false), calledComplete (0)
connectFinished (false), hasBeenDestroyed (false), calledComplete (0)
{
downloaded = -1;
@ -422,7 +422,16 @@ struct BackgroundDownloadTask : public URL::DownloadTask
~BackgroundDownloadTask()
{
[session release];
if (httpCode != -1)
httpCode = 500;
finished = true;
connectionEvent.signal();
[session invalidateAndCancel];
while (! hasBeenDestroyed)
destroyEvent.wait();
[delegate release];
}
@ -435,7 +444,7 @@ struct BackgroundDownloadTask : public URL::DownloadTask
{
[downloadTask resume];
while (downloaded == -1 && finished == false)
Thread::sleep (1);
connectionEvent.wait();
connectFinished = true;
return ! error;
@ -447,8 +456,9 @@ struct BackgroundDownloadTask : public URL::DownloadTask
NSObject<NSURLSessionDelegate>* delegate;
NSURLSession* session;
NSURLSessionDownloadTask* downloadTask;
bool connectFinished;
bool connectFinished, hasBeenDestroyed;
Atomic<int> calledComplete;
WaitableEvent connectionEvent, destroyEvent;
void didWriteData (int64 totalBytesWritten, int64 totalBytesExpectedToWrite)
{
@ -459,6 +469,8 @@ struct BackgroundDownloadTask : public URL::DownloadTask
if (connectFinished && error == false && finished == false && listener != nullptr)
listener->progress (this, totalBytesWritten, contentLength);
connectionEvent.signal();
}
void didFinishDownloadingToURL (NSURL* location)
@ -470,6 +482,8 @@ struct BackgroundDownloadTask : public URL::DownloadTask
httpCode = 200;
finished = true;
connectionEvent.signal();
if (listener != nullptr && calledComplete.exchange (1) == 0)
{
if (contentLength > 0 && downloaded < contentLength)
@ -513,7 +527,15 @@ struct BackgroundDownloadTask : public URL::DownloadTask
if (listener != nullptr)
listener->finished (this, ! error);
}
}
connectionEvent.signal();
}
void didBecomeInvalidWithError()
{
hasBeenDestroyed = true;
destroyEvent.signal();
}
//==============================================================================
struct DelegateClass : public ObjCClass<NSObject<NSURLSessionDelegate> >
@ -528,6 +550,8 @@ struct BackgroundDownloadTask : public URL::DownloadTask
didFinishDownloadingToURL, "v@:@@@");
addMethod (@selector (URLSession:task:didCompleteWithError:),
didCompleteWithError, "v@:@@@");
addMethod (@selector (URLSession:didBecomeInvalidWithError:),
didBecomeInvalidWithError, "v@:@@@");
registerClass();
}
@ -550,6 +574,11 @@ struct BackgroundDownloadTask : public URL::DownloadTask
{
if (auto state = getState (self)) state->didCompleteWithError (nsError);
}
static void didBecomeInvalidWithError (id self, SEL, NSURLSession*, NSURLSessionTask*, NSError*)
{
if (auto state = getState (self)) state->didBecomeInvalidWithError ();
}
};
};