Skip navigation.
 
mlNSConnection/NSSocketPort per-subthread Mach port leak
FROM : Kirk Kerekes
DATE : Fri Jul 14 18:46:43 2006

RE: <rdar://problem/4621753>

It appears that using a NSSocketPort-based Distributed Object's 
rootProxy in a thread other than the one the NSConnection was created 
in leaks 3 Mach ports for each distinct thread that uses the rootProxy.

• The ports are not released when the thread exits -- they are only 
released when the application terminates.
• The leak appears to be per-thread, not per-access.
• I have only investigated this issue with NSSocketPort.
• I have only investigated this on the "client" side of an NSConnection.

NOTE: you can conveniently track Mach port counts with Activity 
Monitor's "#Ports" column.

This isn't a big issue with apps that are terminated regularly or 
that use Distributed Objects sparingly, but I was forced to 
investigate this by a continuously-running app that makes many 
thousands of NSSocketPort DO calls daily to a remote host and which 
would bring the OS (on the client machine) to its knees in a day or 
two due to this leak.

Restructuring the application to eliminate the use of transient sub-
threads sharing an NSConnection eliminated the problem entirely.
The restructuring combined both of the non-leaking scenarios 
discussed in "Scenarios that effectively do _not_ leak:" below.

Specifics:

If you have a scenario where you establish a connection in the main 
thread, and then pass that connection's rootProxy to multiple 
transient sub-threads (after setting multipleThreadsEnabled), any use 
of that rootProxy in a given sub-thread allocates 3 Mach ports that 
are not released when the thread exits. AFAIK these ports are only 
released  when the application terminates.

I have not been able to find any way to prevent this while preserving 
the overall scenario -- the only "fix" has been to change the program 
design to avoid the repetitive use of transient threads that share a 
NSConnection/NSSocketPort.

I assume that this leak has to do with whatever 
multipleThreadsEnabled does to allow multi-thread access, but that 
assumption has not led me to a successful "fix" that does not involve 
avoiding the leaky scenario entirely.

Summary:

Scenarios that effectively do _not_ leak:

• If you have each transient thread create/discard its own 
NSConnection/NSSocketPort, no port-leak.

• If you create a single "worker" thread that persists as long as the 
application does, and just waits for input from the main thread, only 
one triplet (presumably) of Mach ports leaks. This shouldn't be a 
problem. Apps commonly have 100-200 Mach ports allocated -- Mail.app 
has 409 of them as I write this.

Scenario that leaks:

• If you create an NSConnection in the main thread, and then pass it 
or its rootProxy to multiple transient subthreads, the application 
will leak 3 Mach ports for each subthread in which the rootProxy is 
used to access its remote rootObject.


Scenario that appears to leak but hasn't been exhaustively investigated:

• Create a NSConnection in a transient subthread, and then use it in 
the main thread or other transient threads.

Related mailsAuthorDate
No related mails found.