External kill of an NSThread?

How does one kill an NSThread from another thread? As I read the
documentation, it seems possible only from within the thread, by
calling MPExit(). If I have a thread that hangs, I'd like to kill it
from another thread, but I don't see an API to do this. NSThread
doesn't return a thread id or descriptor, so how does one manage them?

This is highly discouraged, since it cannot be done in a stable
fashion. In specific, if your thread currently has any locks held or
any resources acquired, there is no easy way to unlock or release. In
the worst case, your thread's code could be deep inside the OS and
could be holding internal OS-level locks—if you kill the thread at
that point, your entire app is hung forever.

Basically, it's a bad idea. If your thread is hanging, debug the real
problem and solve the hangs. Don't try to thread-kill.

On Nov 20, 2006, at 6:09 PM, Roland Torres wrote:

> How does one kill an NSThread from another thread? As I read the
> documentation, it seems possible only from within the thread, by
> calling MPExit(). If I have a thread that hangs, I'd like to kill
> it from another thread, but I don't see an API to do this. NSThread
> doesn't return a thread id or descriptor, so how does one manage them?
>
> Roland
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/jstiles%
> 40blizzard.com
>
> This email sent to <jstiles...>

> How does one kill an NSThread from another thread? As I read the
> documentation, it seems possible only from within the thread, by
> calling MPExit(). If I have a thread that hangs, I'd like to kill it
> from another thread, but I don't see an API to do this. NSThread
> doesn't return a thread id or descriptor, so how does one manage them?

Simply: you can't with NSThreads.
A thread will end when it's starting function returns (or something
like MPExit()), and this is a good thing.

I agree with John. You must try to debug the issue instead of just
killing. Technique suggested by Gregory can only work if this thread
get the chance to check some condition but what if it stuck
somewhere...?

Gurmit

On 11/21/06, Gregory Weston <gweston...> wrote:

> Roland Torres wrote:
> >> How does one kill an NSThread from another thread?>
> By setting a flag or otherwise triggering a condition that the thread
> in question has been coded to recognize as a signal to clean up and
> exit at the next opportunity.
>
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Cocoa-dev mailing list (<Cocoa-dev...>)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/<gurmit.teotia...>
>
> This email sent to <gurmit.teotia...>
>

Wouldn't it be better to handle the error that's causing the hang
from within the offending thread? What's the point of encapsulation
if objects keep manipulating each other?

Cheers,
Filipe

>> How does one kill an NSThread from another thread? As I read the
>> documentation, it seems possible only from within the thread, by
>> calling MPExit(). If I have a thread that hangs, I'd like to kill
>> it from another thread, but I don't see an API to do this.
>> NSThread doesn't return a thread id or descriptor, so how does one
>> manage them?
>>
>> Roland

My code makes a call to a 3rd party library (not mine) that issues an
NSData dataWithContentsOfURL: call. It's this call that hangs the
show if it can't reach the URL specified. So I thought I might invoke
it in its own thread and kill it if it hangs. Is there a better way,
without mucking with the 3rd party library?

Roland

On Nov 21, 2006, at 9:14 AM, Filipe Varela wrote:

> Howdy
>
> Wouldn't it be better to handle the error that's causing the hang
> from within the offending thread? What's the point of encapsulation
> if objects keep manipulating each other?
>
> Cheers,
> Filipe
> >>> How does one kill an NSThread from another thread? As I read the
>>> documentation, it seems possible only from within the thread, by
>>> calling MPExit(). If I have a thread that hangs, I'd like to kill
>>> it from another thread, but I don't see an API to do this.
>>> NSThread doesn't return a thread id or descriptor, so how does
>>> one manage them?
>>>
>>> Roland

> My code makes a call to a 3rd party library (not mine) that issues
> an NSData dataWithContentsOfURL: call. It's this call that hangs
> the show if it can't reach the URL specified. So I thought I might
> invoke it in its own thread and kill it if it hangs. Is there a
> better way, without mucking with the 3rd party library?

Check the URL for reachability before attempting to reach it? Search
the archives for "SCNetworkCheckReachabilityByName".

> My code makes a call to a 3rd party library (not mine) that issues
> an NSData dataWithContentsOfURL: call. It's this call that hangs
> the show if it can't reach the URL specified. So I thought I might
> invoke it in its own thread and kill it if it hangs. Is there a
> better way, without mucking with the 3rd party library?

You should run your program under the various leak tools to determine
if canceling the thread results in memory leaks.

But, in any case, you should skip this thread stuff altogether, use
asynchronous communication to download the necessary data to a file
and then pass a file:// URL into the 3rd party library. Good luck!

Canceling a thread in this way is very likely to leave the entire
NSURL system in disarray.

I think another poster summed it up best—download the data yourself
in a safe way, and then pass a file:// URL to this library. That will
be simpler code and much much more robust.

Another valid option would be to invoke this code in a thread, and
don't kill the thread if it hangs. If it hangs, let it stay hung.
It's in a separate blocked thread—it's not taking any CPU time and
theoretically isn't doing anything user-visible. When the thread
comes back to life, whenever that might be, end the thread in the
normal way. If it never unblocks, just shrug it off.

On Nov 21, 2006, at 12:11 PM, Roland Torres wrote:

> My code makes a call to a 3rd party library (not mine) that issues
> an NSData dataWithContentsOfURL: call. It's this call that hangs
> the show if it can't reach the URL specified. So I thought I might
> invoke it in its own thread and kill it if it hangs. Is there a
> better way, without mucking with the 3rd party library?
>
> Roland
>
> On Nov 21, 2006, at 9:14 AM, Filipe Varela wrote:
> >> Howdy
>>
>> Wouldn't it be better to handle the error that's causing the hang
>> from within the offending thread? What's the point of
>> encapsulation if objects keep manipulating each other?
>>
>> Cheers,
>> Filipe
>> >>>> How does one kill an NSThread from another thread? As I read the
>>>> documentation, it seems possible only from within the thread, by
>>>> calling MPExit(). If I have a thread that hangs, I'd like to
>>>> kill it from another thread, but I don't see an API to do this.
>>>> NSThread doesn't return a thread id or descriptor, so how does
>>>> one manage them?
>>>>
>>>> Roland

> On Nov 21, 2006, at 12:11 PM, Roland Torres wrote:
> >> My code makes a call to a 3rd party library (not mine) that issues
>> an NSData dataWithContentsOfURL: call. It's this call that hangs
>> the show if it can't reach the URL specified. So I thought I might
>> invoke it in its own thread and kill it if it hangs. Is there a
>> better way, without mucking with the 3rd party library?>
> Check the URL for reachability before attempting to reach it?
> Search the archives for "SCNetworkCheckReachabilityByName".

I did. SCNetworkConnectionFlags() tells me only that the IP portion
of the URL is valid; it doesn't verify that the URL itself is valid.
Is there some method or function I could use for this purpose?

>>> My code makes a call to a 3rd party library (not mine) that
>>> issues an NSData dataWithContentsOfURL: call. It's this call that
>>> hangs the show if it can't reach the URL specified. So I thought
>>> I might invoke it in its own thread and kill it if it hangs. Is
>>> there a better way, without mucking with the 3rd party library?>>
>> Check the URL for reachability before attempting to reach it?
>> Search the archives for "SCNetworkCheckReachabilityByName".>
> I did. SCNetworkConnectionFlags() tells me only that the IP portion
> of the URL is valid; it doesn't verify that the URL itself is valid.

Apologies. Your description of the problem was that the library hangs
when it can't reach the URL. That's a pretty easy situation to work
around but is evidently not actually the situation causing you grief.

How exactly is your problematic URL invalid?

> Is there some method or function I could use for this purpose?

Depends on what is wrong. There are many ways a URL can be "invalid".
It might not conform to the URL spec, the host specified in the URL
might not exist or be reachable, the resource pointed to by the URL
might not exist, etc.

>
> On Nov 21, 2006, at 2:13 PM, Roland Torres wrote:
> >>>> My code makes a call to a 3rd party library (not mine) that
>>>> issues an NSData dataWithContentsOfURL: call. It's this call
>>>> that hangs the show if it can't reach the URL specified. So I
>>>> thought I might invoke it in its own thread and kill it if it
>>>> hangs. Is there a better way, without mucking with the 3rd party
>>>> library?>>>
>>> Check the URL for reachability before attempting to reach it?
>>> Search the archives for "SCNetworkCheckReachabilityByName".>>
>> I did. SCNetworkConnectionFlags() tells me only that the IP
>> portion of the URL is valid; it doesn't verify that the URL itself
>> is valid.>
> Apologies. Your description of the problem was that the library
> hangs when it can't reach the URL. That's a pretty easy situation
> to work around but is evidently not actually the situation causing
> you grief.
>
> How exactly is your problematic URL invalid?
> >> Is there some method or function I could use for this purpose?>
> Depends on what is wrong. There are many ways a URL can be
> "invalid". It might not conform to the URL spec, the host specified
> in the URL might not exist or be reachable, the resource pointed to
> by the URL might not exist, etc.

By "invalid" I just mean that the URL doesn't exist or is
inaccessible. If I could validate the URL before calling the 3rd
party library, then I would be able to avoid the whole thing hanging.
Sadly, Cocoa objects that use -initWithContentsOfURL: just hang
forever on URLs they can't access, whereas Safari, Firefox, curl,
etc., do manage to time out. So I guess I'm looking for some kind of
"isThisURLAccessible(url)" call, or a "getContentsOfURL(url)" call
that doesn't hang forever. I've looked into the CFNetwork programming
guide, but it's really involved, and they don't give working examples
or explain why they're doing what they do.

>> Depends on what is wrong. There are many ways a URL can be
>> "invalid". It might not conform to the URL spec, the host
>> specified in the URL might not exist or be reachable, the resource
>> pointed to by the URL might not exist, etc.>
> By "invalid" I just mean that the URL doesn't exist or is
> inaccessible. If I could validate the URL before calling the 3rd
> party library, then I would be able to avoid the whole thing
> hanging. Sadly, Cocoa objects that use -initWithContentsOfURL: just
> hang forever on URLs they can't access,

Are you sure? I just tried [NSData dataWithContentsOfURL:url], and I
couldn't get it to hang. Feeding it a URL to a non-existent host just
results in an NSData object with zero length.

>
> On Nov 21, 2006, at 3:46 PM, Roland Torres wrote:
> >>> Depends on what is wrong. There are many ways a URL can be
>>> "invalid". It might not conform to the URL spec, the host
>>> specified in the URL might not exist or be reachable, the
>>> resource pointed to by the URL might not exist, etc.>>
>> By "invalid" I just mean that the URL doesn't exist or is
>> inaccessible. If I could validate the URL before calling the 3rd
>> party library, then I would be able to avoid the whole thing
>> hanging. Sadly, Cocoa objects that use -initWithContentsOfURL:
>> just hang forever on URLs they can't access,>
> Are you sure? I just tried [NSData dataWithContentsOfURL:url], and
> I couldn't get it to hang. Feeding it a URL to a non-existent host
> just results in an NSData object with zero length.
>
> Here's my test app. <http://muratnkonar.com/source-code/URLTest.zip>

Interesting. You're quite right for invalid URLs, it returns
immediately. But try entering an inaccessible URL like "http://
192.168.0.20" in your little app. It hangs on this for me for about
1min 15secs, but it does come back eventually. This might be
salvagable if there's a way to shorten the wait time.

> On Nov 21, 2006, at 5:29 PM, Murat Konar wrote:>>
>> On Nov 21, 2006, at 3:46 PM, Roland Torres wrote:
>> >>>> Depends on what is wrong. There are many ways a URL can be
>>>> "invalid". It might not conform to the URL spec, the host
>>>> specified in the URL might not exist or be reachable, the
>>>> resource pointed to by the URL might not exist, etc.>>>
>>> By "invalid" I just mean that the URL doesn't exist or is
>>> inaccessible. If I could validate the URL before calling the 3rd
>>> party library, then I would be able to avoid the whole thing
>>> hanging. Sadly, Cocoa objects that use -initWithContentsOfURL:
>>> just hang forever on URLs they can't access,>>
>> Are you sure? I just tried [NSData dataWithContentsOfURL:url], and
>> I couldn't get it to hang. Feeding it a URL to a non-existent host
>> just results in an NSData object with zero length.
>>
>> Here's my test app. <http://muratnkonar.com/source-code/URLTest.zip>>
> Interesting. You're quite right for invalid URLs, it returns
> immediately. But try entering an inaccessible URL like "http://
> 192.168.0.20" in your little app. It hangs on this for me for about
> 1min 15secs, but it does come back eventually. This might be
> salvagable if there's a way to shorten the wait time.

Well, it's not "hung", it's just giving the other end ample time to
respond. Safari and Firefox behave the same way.

This means that you'll have to download the data yourself and feed it
to your 3rd party lib, (if possible). Alternatively, you could use
this technique to preflight your call to your 3rd party lib. Just try
to download some small bit of data to verify that the other end is
alive and ready to play, then call your library.

>
> On Nov 21, 2006, at 6:19 PM, Roland Torres wrote:
> >> On Nov 21, 2006, at 5:29 PM, Murat Konar wrote:>>>
>>> On Nov 21, 2006, at 3:46 PM, Roland Torres wrote:
>>> >>>>> Depends on what is wrong. There are many ways a URL can be
>>>>> "invalid". It might not conform to the URL spec, the host
>>>>> specified in the URL might not exist or be reachable, the
>>>>> resource pointed to by the URL might not exist, etc.>>>>
>>>> By "invalid" I just mean that the URL doesn't exist or is
>>>> inaccessible. If I could validate the URL before calling the 3rd
>>>> party library, then I would be able to avoid the whole thing
>>>> hanging. Sadly, Cocoa objects that use -initWithContentsOfURL:
>>>> just hang forever on URLs they can't access,>>>
>>> Are you sure? I just tried [NSData dataWithContentsOfURL:url],
>>> and I couldn't get it to hang. Feeding it a URL to a non-existent
>>> host just results in an NSData object with zero length.
>>>
>>> Here's my test app. <http://muratnkonar.com/source-code/URLTest.zip>>>
>> Interesting. You're quite right for invalid URLs, it returns
>> immediately. But try entering an inaccessible URL like "http://
>> 192.168.0.20" in your little app. It hangs on this for me for
>> about 1min 15secs, but it does come back eventually. This might be
>> salvagable if there's a way to shorten the wait time.>
> Well, it's not "hung", it's just giving the other end ample time to
> respond. Safari and Firefox behave the same way.
>
>
> Getting data from a URL with adjustable timeout is outlined at
>
> <http://developer.apple.com/documentation/Cocoa/Conceptual/

> URLLoadingSystem/Tasks/UsingNSURLConnection.html>

>
> This means that you'll have to download the data yourself and feed
> it to your 3rd party lib, (if possible). Alternatively, you could
> use this technique to preflight your call to your 3rd party lib.
> Just try to download some small bit of data to verify that the
> other end is alive and ready to play, then call your library.

If he's already willing to spin off a thread to do the work, all he
needs to do is wait for the thread to complete.
Why kill the thread early? Just let it take however long it needs,
and if the user gets tired of waiting, let them cancel and then sweep
up after the thread whenever dataWithContentsOfURL:url returns.

>
> On Nov 21, 2006, at 6:43 PM, Murat Konar wrote:>>
>> On Nov 21, 2006, at 6:19 PM, Roland Torres wrote:
>> >>> On Nov 21, 2006, at 5:29 PM, Murat Konar wrote:>>>>
>>>> On Nov 21, 2006, at 3:46 PM, Roland Torres wrote:
>>>> >>>>>> Depends on what is wrong. There are many ways a URL can be
>>>>>> "invalid". It might not conform to the URL spec, the host
>>>>>> specified in the URL might not exist or be reachable, the
>>>>>> resource pointed to by the URL might not exist, etc.>>>>>
>>>>> By "invalid" I just mean that the URL doesn't exist or is
>>>>> inaccessible. If I could validate the URL before calling the
>>>>> 3rd party library, then I would be able to avoid the whole
>>>>> thing hanging. Sadly, Cocoa objects that use -
>>>>> initWithContentsOfURL: just hang forever on URLs they can't
>>>>> access,>>>>
>>>> Are you sure? I just tried [NSData dataWithContentsOfURL:url],
>>>> and I couldn't get it to hang. Feeding it a URL to a non-
>>>> existent host just results in an NSData object with zero length.
>>>>
>>>> Here's my test app. <http://muratnkonar.com/source-code/

>>>> URLTest.zip>

>>>
>>> Interesting. You're quite right for invalid URLs, it returns
>>> immediately. But try entering an inaccessible URL like "http://
>>> 192.168.0.20" in your little app. It hangs on this for me for
>>> about 1min 15secs, but it does come back eventually. This might
>>> be salvagable if there's a way to shorten the wait time.>>
>> Well, it's not "hung", it's just giving the other end ample time
>> to respond. Safari and Firefox behave the same way.
>>
>>
>> Getting data from a URL with adjustable timeout is outlined at
>>
>> <http://developer.apple.com/documentation/Cocoa/Conceptual/

>> URLLoadingSystem/Tasks/UsingNSURLConnection.html>

>>
>> This means that you'll have to download the data yourself and feed
>> it to your 3rd party lib, (if possible). Alternatively, you could
>> use this technique to preflight your call to your 3rd party lib.
>> Just try to download some small bit of data to verify that the
>> other end is alive and ready to play, then call your library.>
> If he's already willing to spin off a thread to do the work, all he
> needs to do is wait for the thread to complete.
> Why kill the thread early? Just let it take however long it needs,
> and if the user gets tired of waiting, let them cancel and then
> sweep up after the thread whenever dataWithContentsOfURL:url returns.
>

Yes, this makes a lot of sense, especially since it *is* going to
timeout eventually. I'll just "abandon" the thread (from the user
point of view). When it does complete, I call MPExit() from within
the thread, and it's all good.

> On Nov 21, 2006, at 6:46 PM, John Stiles wrote:>>
>> On Nov 21, 2006, at 6:43 PM, Murat Konar wrote:>>>
>>> On Nov 21, 2006, at 6:19 PM, Roland Torres wrote:
>>> >>>> On Nov 21, 2006, at 5:29 PM, Murat Konar wrote:>>>>>
>>>>> On Nov 21, 2006, at 3:46 PM, Roland Torres wrote:
>>>>> >>>>>>> Depends on what is wrong. There are many ways a URL can be
>>>>>>> "invalid". It might not conform to the URL spec, the host
>>>>>>> specified in the URL might not exist or be reachable, the
>>>>>>> resource pointed to by the URL might not exist, etc.>>>>>>
>>>>>> By "invalid" I just mean that the URL doesn't exist or is
>>>>>> inaccessible. If I could validate the URL before calling the
>>>>>> 3rd party library, then I would be able to avoid the whole
>>>>>> thing hanging. Sadly, Cocoa objects that use -
>>>>>> initWithContentsOfURL: just hang forever on URLs they can't
>>>>>> access,>>>>>
>>>>> Are you sure? I just tried [NSData dataWithContentsOfURL:url],
>>>>> and I couldn't get it to hang. Feeding it a URL to a non-
>>>>> existent host just results in an NSData object with zero length.
>>>>>
>>>>> Here's my test app. <http://muratnkonar.com/source-code/

>>>>> URLTest.zip>

>>>>
>>>> Interesting. You're quite right for invalid URLs, it returns
>>>> immediately. But try entering an inaccessible URL like "http://
>>>> 192.168.0.20" in your little app. It hangs on this for me for
>>>> about 1min 15secs, but it does come back eventually. This might
>>>> be salvagable if there's a way to shorten the wait time.>>>
>>> Well, it's not "hung", it's just giving the other end ample time
>>> to respond. Safari and Firefox behave the same way.
>>>
>>>
>>> Getting data from a URL with adjustable timeout is outlined at
>>>
>>> <http://developer.apple.com/documentation/Cocoa/Conceptual/

>>> URLLoadingSystem/Tasks/UsingNSURLConnection.html>

>>>
>>> This means that you'll have to download the data yourself and
>>> feed it to your 3rd party lib, (if possible). Alternatively, you
>>> could use this technique to preflight your call to your 3rd party
>>> lib. Just try to download some small bit of data to verify that
>>> the other end is alive and ready to play, then call your library.>>
>> If he's already willing to spin off a thread to do the work, all
>> he needs to do is wait for the thread to complete.
>> Why kill the thread early? Just let it take however long it needs,
>> and if the user gets tired of waiting, let them cancel and then
>> sweep up after the thread whenever dataWithContentsOfURL:url returns.
>> > Yes, this makes a lot of sense, especially since it *is* going to
> timeout eventually. I'll just "abandon" the thread (from the user
> point of view). When it does complete, I call MPExit() from within
> the thread, and it's all good.
>
> Thanks for your help, guys, I learned a lot!
> Roland

Be a little bit careful with leaving the thread running. Check that
there isn't an issue if the user cancels and then you start another
thread up so that there are two threads running. Make sure you get
expected behaviour when he first one terminates before the second one
has finished.

I haven't followed this topic from the beginning so forgive me if
this doesn't seem applicable.

> On Nov 21, 2006, at 6:46 PM, John Stiles wrote:>>
>> If he's already willing to spin off a thread to do the work, all he
>> needs to do is wait for the thread to complete.
>> Why kill the thread early? Just let it take however long it needs,
>> and if the user gets tired of waiting, let them cancel and then
>> sweep up after the thread whenever dataWithContentsOfURL:url returns.
>> > Yes, this makes a lot of sense, especially since it *is* going to
> timeout eventually. I'll just "abandon" the thread (from the user
> point of view). When it does complete, I call MPExit() from within
> the thread, and it's all good.

Why are you calling MPExit() from an NSThread? You'd likely want to
use [NSThread exit], but even that shouldn't generally be necessary.
Also, ISTR having problems using +[NSData dataWithContentsOfURL:] in a
thread to load a file from a web server; it's not clear to me if the
underlying mechanism it uses is thread safe.