I regularly use ssh-agent with a subcommand; my X11 session is spawned through ssh-agent, and sometimes i'll run a special agent for a certain subset of commands, like this: ssh-agent bash ... and then do work within that shell. From the man page:> If a commandline is given, this is executed as a subprocess of the agent. > When the command dies, so does the agent.But looking at the process table (and at ssh-agent.c) this isn't what actually happens. It looks like the agent lives on as the subprocess, and the subcommand is execed from the parent process. This has troublesome implications for the agent being able to detect when the command dies, since it can't rely on SIGCHLD handlers. Indeed, check_parent_exists() relies on simply storing the process ID and checking to see whether such a process is signalable. Given that process IDs tend to be relatively small numbers (15 bits on Linux), and are reused frequently, it's not hard to imagine this test giving a false positive. It's also troublesome for process supervision -- if i invoke ssh-agent and i want to ensure that i know when the agent dies (via SIGCHLD), invoking it with a subcommand will obscure the ssh-agent's dying sigchld from my supervising process. That is, the subcommand can continue living (as the supervising process' immediate child) even if the agent segfaults or terminates due to ssh-agent -k or any other reason. Is there a reason for doing things in this order? Is there interest in a patch to make the code behave as documented in the man page? --dkg -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 1030 bytes Desc: OpenPGP digital signature URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20110509/5cd975bd/attachment.bin>
Daniel Kahn Gillmor wrote:> It looks like the agent lives on as the subprocess, and the subcommand > is execed from the parent process. > > This has troublesome implications for the agent being able to detect > when the command dies, since it can't rely on SIGCHLD handlers. Indeed, > check_parent_exists() relies on simply storing the process ID and > checking to see whether such a process is signalable. Given that > process IDs tend to be relatively small numbers (15 bits on Linux), and > are reused frequently, it's not hard to imagine this test giving a false > positive.Such premature reuse looks like an OS bug, although it could theoretically happen. Making the original ssh-agent a process group can probably avoid it, though:> > > 4.12 Process ID Reuse > > A process group ID shall not be reused by the system until the process > group lifetime ends. > > A process ID shall not be reused by the system until the process > lifetime ends. In addition, if there exists a process group whose > process group ID is equal to that process ID, the process ID shall not > be reused by the system until the process group lifetime ends. A > process that is not a system process shall not have a process ID of 1. >http://pubs.opengroup.org/onlinepubs/009604599/basedefs/xbd_chap04.html Another option to ensure it is our real parent would be to use getpid() and look if we have been reparented, although it would need to be careful with getpid() wrappers.> It's also troublesome for process supervision -- if i invoke ssh-agent > and i want to ensure that i know when the agent dies (via SIGCHLD), > invoking it with a subcommand will obscure the ssh-agent's dying sigchld > from my supervising process. That is, the subcommand can continue > living (as the supervising process' immediate child) even if the agent > segfaults or terminates due to ssh-agent -k or any other reason. > > Is there a reason for doing things in this order? Is there interest in > a patch to make the code behave as documented in the man page?I guess it's so you can supervise the "right process", as the important one would be the parameter, so you could replace transparently the called command with "ssh-agent oldcommand". It's also cleaner having the agent showing as child of bash. It's part of your bash session (although 'adopted').
On 2011-05-09 at 12:06 -0400, Daniel Kahn Gillmor wrote:> I regularly use ssh-agent with a subcommand; my X11 session is spawned > through ssh-agent, and sometimes i'll run a special agent for a certain > subset of commands, like this: > > ssh-agent bash > > ... and then do work within that shell. From the man page: > > > If a commandline is given, this is executed as a subprocess of the agent. > > When the command dies, so does the agent. > > But looking at the process table (and at ssh-agent.c) this isn't what > actually happens. > > It looks like the agent lives on as the subprocess, and the subcommand > is execed from the parent process.No, that's not how Unix works. A child process can't indirectly cause its parent to run something without pre-arranged RPCs to communicate application-layer instructions to do so, which I doubt your shell has. There is a common idiom to use: eval `ssh-agent -s` to set up ssh which results in the process layout you describe. This is probably happening somewhere that you just haven't tracked down yet. If you really can't track it down, mv ssh-agent to ssh-agent.real and write a wrapper-script which calls pstree, writing the output to a log-file, before exec'ing ssh-agent.real and wait for that to track it down.
On Mon, 09 May 2011, Daniel Kahn Gillmor wrote:>check_parent_exists() relies on simply storing the process ID and >checking to see whether such a process is signalable.I reported a bug around that code in April 2006. See <http://lists.mindrot.org/pipermail/openssh-unix-dev/2006-April/024144.html> for the problem and a patch that still works for me. --apb (Alan Barrett)
Reasonably Related Threads
- [Bug 1905] New: check_parent_exists() logic does not cover all cases
- [Bug 1777] New: KnownHostsCommand
- [PATCH 0/7] copy-in/copy-out: Capture errors from tar subprocess (RHBZ#1267032).
- [PATCH libnbd] api: New nbd_kill_command API for sending a signal to the command subprocess.
- Re: [PATCH libnbd] api: New nbd_kill_command API for sending a signal to the command subprocess.