gpg-agent and launchd
stephane at sente.ch
Fri Mar 21 18:32:07 CET 2008
I'd like to see support of launchd in gpg-agent.
"launchd is a unified, open source service management framework for
starting, stopping and managing daemons, programs and
It is open-source <http://launchd.macosforge.org/>, under apache
license, and is, under Darwin/MacOSX, responsible to launch all
daemons and agents, based on different criteria, and will relaunch
them if necessary. It replaces init, watchdogd, crond, etc.
Though apache license is incompatible with GPL, launchd is a system
component on OSX (this is even the key component, with PID 1). That
shouldn't cause problem, would it?
The goal is to have a well-integrated agent under MacOSX 10.5: the
agent is launched when user logs in, is relaunched automatically in
case of failure, and is stopped when user logs out. This is already
achievable currently, but there are some limitations:
- as gpg-agent runs as a daemon, we cannot watchdog it, and relaunch
it automatically, without an external watch dog process
- as we cannot make all user processes inherit from the environment
variables of gpg-agent (user processes don't read the ~/.login or
whatever), we need to stick with standard socket path, which works
only if the home directory is mounted as a local file system
- when user logs out, gpg-agent is not terminated automatically
On a technical POV, a program launched by launchd must respect the
following constraints (copied from launchd.plist(5) man page):
It MUST NOT:
• Call daemon(3).
• Do the moral equivalent of daemon(3) by calling
have the parent process exit(3) or _exit(2).
It SHOULD NOT:
• Setup the user ID or group ID.
• Setup the working directory.
• Close "stray" file descriptors.
• Change stdio(3) to /dev/null.
• Setup resource limits with setrusage(2).
• Setup priority with setpriority(2).
• Ignore the SIGTERM signal.
• Launch on demand given criteria specified in the XML
list. More information can be found later in this man
• Catch the SIGTERM signal.
Avoiding fork() is possible, as it is already done for Win32. Avoiding
the chdir() too, as well as avoiding changing uig, gid, sid. I found
no setrusage() nor setpriority(), at first look. SIGTERM is not
ignored, and actually used by the code to terminate properly. I have
no idea about the two other constraints, Close "stray" file
descriptors, and Change stdio(3) to /dev/null.
Launching the agent on demand is unfortunately not possible: though we
can configure launchd to create a secure socket, pass it through an
environment variable, and launch gpg-agent only when the secure socket
is being accessed, this is not possible for gpg-agent, because agent
client processes (gpg) expect the GPG_AGENT_INFO to contain the socket
path, the agent pid, and a version number. This cannot work for us, as
the pid is unknown until the agent has been launched, and the created
environment variable is only the socket path. Anyway, launching the
agent at user's login works fine too.
I modified gpg-agent 2.0.8 to add support for launchd: I had to modify
I added a new command, --launchd, which is exclusive with --daemon and
--server, and does currently the following:
- it creates sockets, like in daemon mode
- it does not fork - this is forbidden
- it does not run any program on the command line - this is forbidden
- it does not print the environment variables (though it might, maybe)
- it passes back to launchd the environment variables; launchd will
make all user processes inherit of these variables
- it does not detach from tty (I don't know what this means and what
are the consequences)
- it doesn't chdir("/"), but the launchd plist sets the working dir to
"/", so it should be equivalent
- it removes the environment variables from launchd, when terminating
Is there any interest here to review and maybe include that code
(available on demand) into gpg-agent?
More information about the Gnupg-devel