The lack of copy and paste on the iPhone is a topic that has received a ton of attention since the iPhone’s release and probably one that will get even attention more once they finally add it. Imagine, for just one moment, the uproar that would transpire if you didn’t have copy and paste on your Mac. Hard to imagine, I know. Unfortunately, however, that’s exactly what happened to my MacBook Pro the other night.

I can’t remember the exact details, but from my memory, it just flat-out stopped working out of nowhere. One minute I was browsing the web and news feeds, and the next moment, copy and paste were gone. I could select and copy text in Mail, but trying to paste it in OmniWeb resulted in a “Beep”. The worst was this problem continued even after rebooting.

For those that don’t know, copy and paste — and cut — between OS X applications is handled by pboard, the pasteboard server. The pasteboard server runs continuously in the background (check it out on your own machine using Activity Monitor). When you copy (or cut) something in an application, that application sends that data (text, image, or whatever) to the pasteboard server. And when you paste, the destination application retrieves the data from the pasteboard server. As usual, there’s more to it, but that’s copy and paste on Mac OS X in a nutshell.

Why a separate process, rather than having the destination application talk directly to the sending application? This allows for the case where you copy text in one application, quit that application, and then paste in another. Plus, how would the receiving application know which application is the sending application? If it tried to ask every application on the system, it would be inefficient. Having a separate pasteboard server means the retrieving application always knows where to look.

This is all handled behind the scenes for both users and developers. Cocoa developers interact with the pasteboard server using the NSPasteboard class. Drag and drop is also handled by the pasteboard server and is really a specialized case of copy and paste. If you have the developer tools installed, there’s a cool utility called Clipboard Viewer to watch what’s on the pasteboard (I believe “clipboard” is the classic MacOS term for “pasteboard”). It’s located at:

/Developer/Applications/Utilities/Built Examples

So, given how important the pasteboard server is to copy and paste, if it goes away, then naturally copy and paste stop working. The sending application has no place to send data and the receiving application has no place to find data. And that’s exactly what happened. Somehow pboard died. Okay, all applications have bugs, I thought, maybe it just crashed and needed to be restarted. Not sure of the “proper” way to restart just pboard, I decided to reboot. Surely, pboard would start up anew and copy and paste would happily begin working again.

This is where it gets weird. Even after a reboot, I had no copy, no paste, and no pboard. At this point, I started looking at the system logs. All of a sudden, my local Apache instance wasn’t starting either. Neither was ssh-agent. Clearly something really bad was going on.

All of these background processes are handled by launchd, so I tried to see what launchd had to say about pboard:

% launchctl list com.apple.pboard
launch_msg(): Socket is not connected

Okay, now that’s a strange error message. Now launchd itself seemed broken. With my system quickly falling apart at the seams, I was nearly out of ideas and ready to re-install. Luckily, I found the problem (and an easy solution!) at the eleventh hour.

I was poking around at the command line and suddenly noticed that /tmp was gone. /tmp is used for temporary files on Unix, and it was completely missing. Well, /private/tmp to be precise. /tmp is a symlink to /private/tmp on Mac OS X. Surely this couldn’t be the root cause of all my problems. Why yes, yes it was (and stop calling me Shirley!).

All I had to do was recreate /private/tmp (with the correct permissions, of course) and reboot:

% sudo mkdir -p -m 01777 /private/tmp

All was back to normal.

Except that this was all really weird. If the /tmp directory is so important to correct system behavior, shouldn’t the OS make sure it exists? I know that prior to OS X 10.5, /private/tmp was cleaned and recreated on every boot. In fact, you can see this snippet in /etc/rc on 10.4.11 (the last line re-creates /private/tmp unconditionally):

# Clean out /private/tmp.
if [ -d /private/tmp ]; then
        # blow away any _tmp_ in case it exists as well
        if [ -e /private/_tmp_ ]; then
                chflags -R -P 0 /private/_tmp_
                rm -rf /private/_tmp_
        fi
        mv /private/tmp /private/_tmp_
        chflags -R -P 0 /private/_tmp_
        RMRF_ITEMS="$RMRF_ITEMS /private/_tmp_"
fi
mkdir -p -m 01777 /private/var/tmp /private/tmp

On 10.5+, /etc/rc is gone, and its functionality is replaced by launchd itself. I’m not sure if launchd cleans out /private/tmp anymore (I didn’t see it in the code), and it’s certainly not recreating it. I filed bug #6186126 on this, thinking that it should recreate /private/tmp, as it did on 10.4 and earlier. That would save a lot of frustration should /private/tmp mysteriously (or not mysteriously) go away.

I still don’t know what deleted /private/tmp to begin with, which is rather disconcerting, especially since you need root privileges to delete it. So I’ll still be keeping a close eye on that machine and hard drive. However, you might want to add this to the list of “things to check” if your system starts acting really strange. /tmp is used by a lot of applications, especially Unix applications, and I’m guessing that most of them don’t handle the case of a missing /tmp very gracefully.