Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Notes and workarounds for accessing the Mac OS X pasteboard in tmux sessions. Note: The pu branch (“Proposed Updates”) may be rewound without notice.
C Makefile
tree: 8d99ce8566

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.


Processes started under "stock" tmux and screen can not access the
Mac OS X pasteboard.

Apple publishes their modified source for screen.


Someone adapted Apple's 10.6 screen changes to tmux.

Basically, it involves replacing the call to daemon() with a
call to the undocumented function _vprocmgr_detach_from_console().

    Note: 'upstream' screen vs. Apple's 10.6.6 screen

        The call to _vprocmgr_detach_from_console was a pure
        addition, not a replacement for the fork() like the above
        patch does in tmux.

When I patched recent tmux HEAD (via
git:// master), the resulting
under-tmux shells could access the pasteboard (e.g. pbpaste).
However, it resulted in many warning messages from libevent.

    [warn] event_del: event has no event_base set.

I see eleven of these messages just doing

    ./tmux new 'echo something'

Additionally, if I start a shell (instead of just an "echo"), I see
the message after every key press. Until I press ESC. Then the per
key press messages disappear, and I only see ten of the messages
after tmux exiting the shell (and thus tmux).

What I want to do here is to make a minimal test rig for
daemon()/_vprocmgr_detach_from_console() and libevent to see what
can be done to ameliorate the problem.

Findings from testing on 10.6.6:

    Calling _vprocmgr_detach_from_console() by itself does not
    impede a child from successfully using pbpaste. The result from
    getpid() is the same before and after the call, so whatever it
    does, it does not fork internally.
    Calling daemon() does prevent a child from successfully using pbpaste.

    A hand-rolled daemon() (fork, setsid, open(/dev/null), dup2 for
    0-2) does not impede a child from successfully using pbpaste.

I was able to dig up daemon() and the vproc functions. Here are the
sources for 10.6.6:

The annoying thing that the system() daemon() is doing is that it
moves to the root "bootstrap namespace". The bootstrap service is
what programs use to get access to other services. Being in the root
namespace prevents the process from accessing the pasteboard
service (which is only in a per-user namespace in 10.5 and beyond).

After some more subtle testing, I found that the call to
_vprocmgr_detach_from_console() lets the children of tmux (the whole
per-session bootstrap namespace?) maintain access to the pasteboard
even after the session initiator has exited. For example: during
a GUI login, SSH back to localhost, start a new tmux server there,
detach from it. Attach from elsewhere and pbpaste still works. Exit
from the SSH connection (the one that started the tmux process).
If we used _vprocmgr_detach_from_console, then the children of tmux
can still access the pasteboard. If we did not call it, then they
lose access to the pasteboard (the namespace was revoked?).

Possible Resolutions

  Use daemon() from compat/daemon.c and _vprocmgr_detach_from_console()

      check for 'broken' daemon would require Darwin-specific stuff
        Not even sure how best to do that. Could check whether
        (after a call to daemon())  the output from `launchctl
        bslist` contains "" (or do the
        equivalent in straight C, if it does not use even more
        private APIs).
      assume Darwin daemon() is broken for our purposes
        use compat/daemon
          would it be deterministicly used instead of libSystem daemon()?
            could #define daemon compat_daemon for compat/daemon.c and server.c
        still need call to _vprocmgr_detach_from_console()
          make osdep_daemon() and call it after (compat) daemon()

  Use system daemon() and find a way to re-attach to the/a user

    Per TN2083, launchd creates non-GUI per-session namepsaces for
    accepted SSH connections based on the SSH launchd plist having
    a SessionCreate key. Looking at the launchd code, it seems that
    it does this via CreateSession(0,0) from the Security Framework.

        launchd_SessionCreate in

    Or maybe _vprocmgr_move_subset_to_user(), like the 10.5(?)
    screen code used?
Something went wrong with that request. Please try again.