Saturday, August 23, 2003

NSObjectInaccessibleException

Today I learned something about distributed objects and NSConnection. When I have an object that I want to access from multiple threads (or that I want to receive messages in the main thread), I make it a DO server, and I give each thread a proxy. I’ve been creating the proxies like this:

NSConnection *clientConnection = [[[NSConnection alloc]
                           initWithReceivePort:[serverConnection sendPort]
                                      sendPort:[serverConnection receivePort]];
id proxy = [clientConnection rootProxy];

There is only one serverConnection per server, but that’s OK because I call [serverConnection enableMultipleThreads]. The problem was that I was inexplicably getting NSObjectInaccessibleExceptions saying “NSDistantObject access attempted from another thread” when two threads tried to create proxies for the same server.

The above code makes it look like there’s one clientConnection per thread/proxy. However, the documentation for the -initWithReceivePort:sendPort: method says:

If an NSConnection with the same ports already exists, releases the receiver, retains the existing NSConnection, and returns it.

This means that the connection will be shared among multiple threads and you have to call [clientConnection enableMultipleThreads] to avoid the NSObjectInaccessibleException. I’m not a big fan of this design, because I don’t think code using a given connection should have to know when some other code is using a connection with the same ports. But there you have it.

5 Comments RSS · Twitter

Wow, am I ever glad I found this page! The *only* result for my Google search, and it saved my hide. Thanks for posting this, even if it was 2 years ago!

I've got to emphasis what Jon said ... this page was a lifesaver!

Many thanks for Michael ...

Another vote of thanks. I had been getting this message, which didn't explicitly say it was an NSObjectInaccessibleException. Sometimes you gotta fix your bugs using Google...

*** NSThread: ignoring exception 'NSDistantObject access attempted from another thread' that raised during delayed perform of target 0x3a99f0 and selector '_didCloseFile:'

I do not know if the docs have changed since you wrote this post, but the relevant bit currently reads:

If an NSConnection exists that uses the same ports, but switched in role, then the new NSConnection communicates with it. Messages sent to a proxy held by either NSConnection are forwarded through the other NSConnection. This rule applies both within and across address spaces. This behavior is useful for setting up distributed object connections between threads within an application.

Regardless, enableMultipleThreads is required to avoid the NSObjectInaccessibleExceptions.

Leopard has multiple threads enabled by default, so folks may run into this problem on Tiger when it works fine on Leopard.

Leave a Comment