Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

FW: Crash in CFRunLoopSourceIsValid



Fw just because the original message didn't appear on the list.

I think it's a valuable explanation of this topic.

Thank you, Chris!

Regards

Dirk




------ Weitergeleitete Nachricht
Von: Chris Kane <email@hidden>
Datum: Tue, 11 May 2004 11:01:52 -0700
An: Dirk Musfeldt <email@hidden>
Cc: email@hidden
Betreff: Re: Crash in CFRunLoopSourceIsValid

It could be due to a subtle race condition in the code:

I'll assume you properly have a hard retain on runLoopSource, that you
clean up at some point after you call CFRunLoopSourceInvalidate() in
StopStandardRunLoop(). I'll ignore issues you might have there.

If runLoopSource is the only source in the run loop (on that other
thread), and from the code that's what it looks like (let's in fact
assume that for the moment), then the CFRunLoopRun() function will exit
as soon as there are no sources to process. This happens when you call
CFRunLoopSourceInvalidate() -- the source removes itself from the run
loop, leaving the run loop on that thread empty. [More specifically,
leaving the default run loop mode in that run loop empty, since that is
the mode that CFRunLoopRun() runs.]

That thread may get scheduled to the processor immediately and run
through to exiting, at which point CF will clean up its retain on the
run loop object (you can think of it as keeping one on behalf of the
thread) for that thread, which if that is the last retain will cause
the run loop object to be destroyed.

This leaves gStandardRunLoopRef pointing at a freed object, and
CFRunLoopStop() is then called on a freed object.

Sometimes the thread scheduling happens in this way, and sometimes then
you get a crash. Sometimes the thread scheduling happens in some other
way, and no crash because you luck out.

Generally as a good convention, public globals and static globals
should hold a hard retain on whatever they're pointing to. And
generally this retain should be taken before the variable itself is
assigned to, to avoid any subtle race conditions of other threads
looking at the variable or subtle scheduling sequences:

gStandardRunLoopRef = CFRetain(CFRunLoopGetCurrent());

This must be balanced by an explicit release, which should be done in
the other thread which is accessing this global.

CFRelease(gStandardRunLoopRef);
gStandardRunLoopRef = kRunLoopCancelled;

If more threads were possibly looking at this global, things would be
more complicated, and probably some other (or additional) technique
would be required, to avoid anybody ever looking at a freed run loop
object.

Another simple fix would be to move the invalidate after the
CFRunLoopStop(), but the global variable should still have a hard
retain, so I wanted to present that first.


Finally, NOTE (a general reminder for everybody reading this): you
might be tempted to use the fact that CFRunLoopRun() will return when
there are no more input sources registered [in the default mode], and
simply use the invalidation of the source to cause the thread to exit.
However, you CANNOT depend on your sources ("the ones you put in")
being the only sources in the run loop. Other frameworks may put in
their own sources for whatever needs they have, even in that background
thread which is "only doing your stuff", and those other things aren't
responsible for getting their sources out of the run loop at the right
moment just so that CFRunLoopRun() will return. The "return when
empty" semantic of CFRunLoopRun() is documented
(http://developer.apple.com/documentation/CoreFoundation/Reference/
CFRunLoopRef/Reference/function_group_1.html), so that developers are
warned that it can return, not so that they can depend on it returning.


Chris Kane
CoreFoundation, Apple




------ Ende der weitergeleiteten Nachricht
_______________________________________________
darwin-development mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/darwin-development
Do not post admin requests to the list. They will be ignored.




Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.