Trouble using DO for interthread communication
Trouble using DO for interthread communication
- Subject: Trouble using DO for interthread communication
- From: David Watanabe <email@hidden>
- Date: Fri, 22 Jun 2001 00:18:35 -0700
I've been trying to implement a method that would allow me to send
messages into the main thread from various worker threads (primarily to
update app state and do appkit stuff). I know about Omni's solution for
this in OmniFoundation -- but I'd rather not have to include all of
OmniFoundation just to get this one little thing working (and I'd rather
learn how to do it myself).
I've been experimenting with DO as a means to accomplish this, basically
following the thread communication example code in NSConnection.
However, I'm experiencing some strange errors when attempting to access
a rootProxy object from threads -- sometimes it works, but on rare
occasions I will get an NSInternalInconsistencyException when trying to
access the DO rootProxy. The strange thing is that if I handle the
exception and let the program continue, the next call to rootProxy will
likely work. Ultimately, though, after a few hundred (or just a few)
calls to rootProxy, the app will die, usually with a SIGBUS.
So, I am wondering whether I am simply doing something wrong, or if I am
seeing a bug. I've never used DO before, so I'm inclined to think it is
me. I've attached some sample code which exercises this peculiarity
along with some sample output. I'm running 10.0.4 on a Powerbook
(pismo) using the 1.0.1 dev tools.
The sample very simply initializes the connection, then proceeds to
spawn a thread that tries to access the [_clientConnection rootProxy]
(it doesn't actually try to do anything with it). The thread then
spawns a new thread. As I'm typing this, I realize that the threads
should be executing sequentially -- but this problem doesn't happen if I
put the rootProxy request in a while(1) loop. I've put in an NSLock
that is useless here but possibly useful in a real multithreaded app.
// BEGIN SAMPLE CODE
#import <Foundation/Foundation.h>
@interface Irritation : NSObject {
NSConnection* _clientConnection;
NSLock* _lock;
}
- (void) threadRun: (id) parameter;
- (NSConnection*) bindToCurrentRunLoop;
@end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Irritation* instance = [[Irritation alloc] init];
[instance bindToCurrentRunLoop];
[NSThread detachNewThreadSelector:@selector(threadRun:)
toTarget:instance
withObject:instance];
[[NSRunLoop currentRunLoop] run];
[pool release];
return 0;
}
@implementation Irritation
- (void) threadRun: (id) instance;
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// the lock is for good measure, but doesn't seem to help
[_lock lock];
NSLog(@"thread: %@", [NSThread currentThread]);
NS_DURING
NSLog(@"proxy: %@", [_clientConnection rootProxy]);
NS_HANDLER
// just log the error and maybe we'll be able to continue on
NSLog(@"%@, %@", [localException name], localException);
NS_ENDHANDLER
[_lock unlock];
[NSThread detachNewThreadSelector:@selector(threadRun:)
toTarget:self
withObject:self];
[pool release];
}
- (id) init;
{
[super init];
_lock = [[NSLock alloc] init];
return self;
}
- (NSConnection*) bindToCurrentRunLoop;
{
NSPort *port1, *port2;
NSConnection* vendorConnection;
NSArray* portArray;
port1 = [[NSPort port] retain];
port2 = [[NSPort port] retain];
vendorConnection = [[NSConnection alloc]
initWithReceivePort: port1
sendPort: port2];
[vendorConnection setRootObject: self];
portArray = [NSArray arrayWithObjects: port2, port1, nil];
[NSThread
detachNewThreadSelector:@selector(initializeClientConnection:)
toTarget:self
withObject:portArray];
return vendorConnection;
}
- (void) initializeClientConnection: (NSArray*) portArray;
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
_clientConnection = [[NSConnection alloc]
initWithReceivePort:[portArray objectAtIndex: 0]
sendPort:[portArray objectAtIndex: 1]];
[_clientConnection retain];
[_clientConnection enableMultipleThreads];
[pool release];
}
@end
// END SAMPLE CODE
// SOME SAMPLE OUTPUT:
All is well before, all is well after:
[snip]
Jun 22 00:05:23 DOIdiocy[1338] thread: Thread 0x77fd0
Jun 22 00:05:23 DOIdiocy[1338] proxy: <Irritation: 0x50000>
Jun 22 00:05:23 DOIdiocy[1338] thread: Thread 0x789a0
Jun 22 00:05:23 DOIdiocy[1338] NSInternalInconsistencyException,
messaging a local proxy
Jun 22 00:05:23 DOIdiocy[1338] thread: Thread 0x78740
Jun 22 00:05:23 DOIdiocy[1338] proxy: <Irritation: 0x50000>
Jun 22 00:05:23 DOIdiocy[1338] thread: Thread 0x79ce0
Jun 22 00:05:23 DOIdiocy[1338] proxy: <Irritation: 0x50000>
Jun 22 00:05:23 DOIdiocy[1338] thread: Thread 0x789a0
Jun 22 00:05:23 DOIdiocy[1338] proxy: <Irritation: 0x50000>
[snip]
A significantly rarer error, but things are still happy after it happens:
[snip]
Jun 22 00:05:27 DOIdiocy[1338] thread: Thread 0x85ad0
Jun 22 00:05:27 DOIdiocy[1338] proxy: <Irritation: 0x50000>
Jun 22 00:05:27 DOIdiocy[1338] thread: Thread 0x85d30
Jun 22 00:05:27 DOIdiocy[1338] NSInternalInconsistencyException,
encodeWithCoder: invalid Proxy 889d0, wire 3
Jun 22 00:05:27 DOIdiocy[1338] thread: Thread 0x89e40
Jun 22 00:05:27 DOIdiocy[1338] proxy: <Irritation: 0x50000>
[snip]
sigh/sob/laugh:
[snip]
Jun 22 00:05:28 DOIdiocy[1338] thread: Thread 0x89400
DOIdiocy has exited due to signal 10 (SIGBUS).
// END SAMPLE OUTPUT
Thanks in advance for any help!!
Dave Watanabe
sciforums.com | webfansite.com