• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
NSURLProtocol thread safety
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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
  • Prev by Date: Re: NSBrowserCell not extensible; need sample using NSButtonCell
  • Next by Date: Re: NSBrowserCell not extensible; need sample using NSButtonCell
  • Previous by thread: Re: Reload Preference Pane in memory
  • Next by thread: Re: How to disable/gray an NSTextfield (used as static text)
  • Index(es):
    • Date
    • Thread