NSURLProtocol thread safety
NSURLProtocol thread safety
- Subject: NSURLProtocol thread safety
- From: Jakob Olesen <email@hidden>
- Date: Fri, 21 Jul 2006 00:23:15 +0200
Is NSURLProtocol thread safe?
I am subclassing NSURLProtocol to implement a custom URL scheme. I
need to handle all requests in a particular thread that I created at
startup. NSURLConnection uses a separate thread for the NSURLProtocol
instances, so in my -startLoading implementation I forward the
request to my data processing thread.
Abbreviated code:
-(void)startLoading
{
isLoading = YES;
[dataThread queueProtocolRequest:self]; // puts self in a queue
for data thread to pick up
}
The data thread then delivers data using this method (called in the
data thread). (I am skipping details with sending the NSURLResponse
here)
- (void)sendData:(NSData*)data;
{
if (isLoading)
[[self client] URLProtocol:self didLoadData:data];
}
Finally, after calling -URLProtocolDidFinishLoading, I get:
-(void)stopLoading
{
isLoading = NO;
}
So far, so good, this actually works. At least until I start
cancelling requests. Then I get crashes. I figured out, what
happened. NSURLConnection is calling -stopLoading just after my data
thread has entered URLProtocol:didLoadData:. -stopLoading returns
immediately, and NSURLConnection starts cleaning up. Meanwhile my
data thread is still running in URLProtocol:didLoadData:. Crash.
So, I added synchronization with an NSRecursiveLock: (Again, I have
omitted callbacks for setting the response and finishing, they are
similar)
- (void) sendData:(NSData*)data;
{
[lock lock];
if (isLoading)
[[self client] URLProtocol:self didLoadData:data];
[lock unlock];
}
-(void)stopLoading
{
[lock lock];
isLoading = NO;
[lock unlock];
}
This way -stopLoading cannot return until the data thread has left
URLProtocol:didLoadData:, and [self client] will not be called again
after that in any thread. (Because I check isLoading before each
call). I can no longer provoke the crash. Everybody is happy.
Except, I still have a bad feeling about this. I am calling the
NSURLProtocolClient from a different thread. Synchronized, yes, but
still a different thread. The documentation doesn't mention threading
at all, except this:
- (void)URLProtocol:(NSURLProtocol *)protocol
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)
challenge
[...] The protocol client guarantees that it will answer the request
on the same thread that called this method. [...]
This comment suggests that the NSURLProtocolClient is thread aware,
but who knows?
I can only find two code examples of an NSURLProtocol subclass: The
PictureBrowser example and WebKit's WebDataProtocol (used for
loadHTMLString:baseURL:) Both are trivial, they do all their work in -
startLoading.
So, am I safe, or do I need to deliver data in the original thread?
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden