Mailing Lists: Apple Mailing Lists

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

Re: Crash in CFRunLoopSourceIsValid



Chris,

I tried to change the code, but I now got another crash. Is it possible that
the pthread_exit() implicitly destroys the CFRunLoop?


Date/Time: 2004-05-13 14:30:34 +0200
OS Version: 10.3.2 (Build 7D24)
Report Version: 2

Command: AlchemyTV DVR
Path: /Applications/AlchemyTV DVR/AlchemyTV
DVR.app/Contents/MacOS/AlchemyTV DVR
Version: AlchemyTV DVR version 2.1 (2.1)
PID: 868
Thread: 0

Exception: EXC_BAD_ACCESS (0x0001)
Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000006

Thread 0 Crashed:
0 com.apple.CoreFoundation 0x90190c0c CFRelease + 0x24
1 Component 0x054054b0 0x53e2000 + 0x234b0
2 Component 0x053efae4 StopStandardRunLoop + 0x74
3 Component 0x053eb9c0
CloseIOService__FUiPUiPP12__CFMachPortPP17__CFRunLoopSourcePP17_opaque_pthre
ad_t + 0xc0
[...]



This is the modified code:


void * MSTStandardCFMRunLoop( void * source)
{
CFRunLoopSourceRef runLoopSource = (CFRunLoopSourceRef)source;

pthread_mutex_lock( &gStandardRunLoopMutex);

if (kRunLoopCancelled != gStandardRunLoopRef) {

gStandardRunLoopRef = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent());

CFRunLoopAddSource( gStandardRunLoopRef, runLoopSource,
kCFRunLoopDefaultMode);

pthread_mutex_unlock( &gStandardRunLoopMutex);

CFRunLoopRun(); // will block until CFRunLoopStop

} else {
// was already cancelled
pthread_mutex_unlock( &gStandardRunLoopMutex);
}

pthread_detach( pthread_self());
pthread_exit( NULL);

return NULL;
}


void StopStandardRunLoop(
pthread_t runLoopThread,
CFRunLoopSourceRef runLoopSource)
{

pthread_mutex_lock( &gStandardRunLoopMutex);

CFRunLoopRef runLoop = gStandardRunLoopRef;

if (runLoopSource && CFRunLoopSourceIsValid (runLoopSource)) {
CFRunLoopSourceInvalidate (runLoopSource);
}

if ((runLoop != nil) && (kRunLoopCancelled != runLoop)) {
CFRunLoopStop( runLoop);
}

CFRelease(gStandardRunLoopRef);
gStandardRunLoopRef = kRunLoopCancelled;// never call CFRunLoopRun again

pthread_mutex_unlock( &gStandardRunLoopMutex);
}



> 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.
>
>

Regards

Dirk
_______________________________________________
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.


References: 
 >FW: Crash in CFRunLoopSourceIsValid (From: Dirk Musfeldt <email@hidden>)



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.