| |||
| [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] |
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: | |
| >Re: Crash in CFRunLoopSourceIsValid (From: Dirk Musfeldt <email@hidden>) |
| Home | Archives | FAQ | Terms/Conditions | Contact | RSS | Lists | About |
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.