Read Me About MachPortDump.txt

Read Me About MachPortDump
==========================
1.1
 
This sample dumps out the Mach port name space of a process.  It is designed to be used as a tool by developers who are writing inter-process communication code on Mac OS X.  Typically this code is based on Mach ports, or some higher-level wrapper around Mach ports.  You can run this sample to check to see whether your code leaks ports.
 
MachPortDump should be compatible with any versions of Mac OS X.  It was built and tested on Mac OS X 10.4.x with Xcode 2.1.
 
Packing List
------------
The sample contains the following items:
 
o Read Me About MachPortDump.txt -- This file.
o MachPortDump.c -- C source code for the program.
o MachPortDump.xcodeproj -- An Xcode 2.1 project for the program.
o MachPortDump.xcode -- An Xcode 1.5 project for the program.
o build -- A folder containing a built universal binary.
 
Using the Sample
----------------
To test the sample, you should change into the directory containing the pre-built executable.
 
$ cd Desktop/MachPortDump/build/Development
$ ls -lh
total 24
-rwxr-xr-x  1 quinn  staff    9K  1 Nov 13:30 MachPortDump
 
If you run the program with the "-?" argument, you get usage.
 
$ ./MachPortDump -?
usage: MachPortDump [options] [ [ pid | name ]... ]
       Send, Receive, SendOnce, PortSet, DeadName = right reference counts
       DNR = dead name request
       -w wide output, with lots of extra info
          flg      = N (no senders) P (port dead) S (send rights)
          seqno    = sequence number
          mscount  = make-send count
          qlimit   = queue limit
          msgcount = message count
          sorights = send-once right count
          pset     = port set count
 
If you run the program with no arguments, it prints out a dump of its own Mach port name space.
 
$ ./MachPortDump 
    Name     Send  Receive SendOnce  PortSet DeadName DNR
    ----     ----  ------- --------  ------- -------- ---
   0x107                 1                                
   0x213                 1                                
   0x307        4                                         
   0x40b        2                                         
   0x50b                 1                                
   0x60b                 1                                
   0x707                 1                                
   0x80b        2                                         
   0x907        3                                         
   0xa03                 1                                
   0xc03                 1                                
 
Each row represents a Mach port right name (that is, the small integer value used by the program as a 'handle' to the port right).  Each column represents a count of the number of times that the name references a particular right.  For example, in the above listing, the name 0x307 holds 4 send right references for a port, while the name 0xc03 holds a single receive right for a port.
 
If you supply a process as an argument (either via PID or name), MachPortDump prints the name space for that process.
 
$ ./MachPortDump Finder
Mach ports for 'Finder' (385):
 
    Name     Send  Receive SendOnce  PortSet DeadName DNR
    ----     ----  ------- --------  ------- -------- ---
   0x107                 1                                
   0x207                 1                                
   0x313                 1                                
   0x40b       12                                         
   0x507        2                                         
   0x60f                 1                                
   0x707                 1                                
   0x807                 1                                
   0x90b     4128                                         
   0xa07        7                                         
   0xb07        1                                         
   0xc03                 1                                
   0xd03        1                                         
   0xe03        1                                         
   0xf03        1                                     yes 
  0x1003                 1                                
  0x1103    48957        1                                
  0x1203                                   1              
[...]
  0xd833        1        1                                
  0xd96b                          1                       
  0xda17        1        1                                
[...]
 
In this example you can see that the Finder holds references to many Mach port rights, including a reference to a port set (0x1203) and a send-once right (0xd96b).  Also note that some names (for example, 0xd833) can reference more than one type of right.  Finally, note that Finder holds 48957 references to a particular send right (0x1103), which is probably a bug.  I'll discuss this in more depth below.
 
If you supply the "-w" flag, MachPortDump prints a bunch of extra information.
 
$ ./MachPortDump -w Finder
[...]
 
I've not included any output because it's too wide to view meaningfully in a standard text document.  You might want to pipe the output to a text editor with soft word wrap turned off.
 
$ ./MachPortDump -w Finder | bbedit
[...]
 
Bug Hunting with MachPortDump
-----------------------------
If you program with Mach directly, or even if you only use high-level wrappers, it's quite easy to accidentally leak Mach port rights.  MachPortDump can help you find those leaks.
 
1. You can run MachPortDump against your program to see if any of the port rights have an excessive reference count.  For example, the right with 48957 references in the Finder (shown above) is very likely to be a bug.
 
2. You can run MachPortDump, capture its output, perform some operation, then run MachPortDump again, and compare its output to the original.  If any new names exist, or any rights have an increased reference count, you should investigate why.
 
3. It might make sense for you to copy chunks of MachPortDump into your own program to implement an automatic debugging facility.  If you plan to do this, read the "Caveats" section (below) before proceeding.
 
While debugging with MachPortDump, remember that many system services are based on top of Mach ports.  Thus, if you notice a port right 'leak', it may be a leak of some other object.  For example, in the System Configuration framework, the SCDynamicStoreRef object contains a reference to a Mach port; if you notice a Mach port leak, it might be that you're actually leaking a SCDynamicStoreRef.
 
Building the Sample
-------------------
The sample was built using Xcode 2.1 on Mac OS X 10.4.  You should be able to just open the project and choose Build from the Build menu.  This will build the MachPortDump tool in the "build" directory.
 
How it Works
------------
Fundamentally this program relies on three Mach routines to do its job.
 
o task_for_pid maps a BSD process ID (PID) to a send right for the controlling task port for the associated Mach task
 
o mach_port_names returns a snapshot of a Mach task's port name space
 
o mach_port_get_refs gets the reference count for a particular right
 
These routines are all public Mach routines, although see the following section for critical information about the Mach API on Mac OS X.
 
Caveats
-------
Apple strongly recommends that developers avoid using Mach APIs directly.  Mach APIs represent the lowest-level interface to the kernel, and thus they are the most likely to change (or become unsupportable) as the kernel evolves.
 
Apple strongly recommends that developers use high-level wrappers around Mach APIs where possible.  For example, rather than use Mach messages directly, you could use CFMessagePort.  You should only use Mach APIs if there is no higher-level alternatively.
 
This sample uses Mach APIs directly, and thus seems to violate the above recommendations.  However, this is justified by the last sentence of the previous paragraph: the job this sample does, displaying information about a Mach task's port right name space, is only possible via the use of Mach APIs.
 
It might make sense for you to copy the techniques used by MachPortDump into your application, to help detect port right leaks and so on.  However, I strongly recommend that you include this code only in your debug build.
 
Credits and Version History
---------------------------
If you find any problems with this sample, mail <dts@apple.com> and I'll try to fix them up.
 
1.0 (Nov 2004) was the first shipping version.
 
1.1 (Jul 2005) was updated to include an Xcode 2.1 project to produce universal binaries; there were no code changes required for it to run correctly on the Developer Transition Systems.
 
Share and Enjoy.
 
Apple Developer Technical Support
Networking, Communications, Hardware
 
20 Jul 2005
 
$Log: Read\040Me\040About\040MachPortDump.txt,v $
Revision 1.3  2005/07/20 15:00:44  eskimo1
Updated to describe version 1.1 changes.
 
Revision 1.2  2004/11/12 16:23:29  eskimo1
Added a missing "be".
 
Revision 1.1.1.1  2004/11/01 14:47:10  eskimo1
First Imported.