cuviper / ssh-pageant

An SSH authentication agent for Cygwin/MSYS to PuTTY's Pageant.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

An Option to Deal With Orphans

WeaverThree opened this issue · comments

Hi! I routinely bomb out my cygwin shells in a way that makes exit traps not run*, and end up with a bunch of ssh-pagent processes happily running along whilst no-one needs them anymore.

Could there be an extra option to make ssh-pagent poll every few minutes that the shell that started it is till running (i'll go through the variable calesthenics to provide the PID of the higher order shell on the command line if required), or perhaps a command line option to kill all ssh-agent instances BUT those provided on the command line?

Thanks!

  • (I actually used trap 'eval $(/usr/bin/ssh-pageant -qk 2>/dev/null)' EXIT instead of setting up a separate onexit file, seemed cleaner)

First, just to get terminology straight, what you describe are more like orphans, processes without a parent (which get reassigned a parent of PID 1). A zombie is a process that has terminated, but has not yet been wait()ed on by the parent (or reaped by PID 1 if it was an orphan). I'll adjust the title to orphan, although even that is not quite accurate here...

My first thought on this was to pine for Linux's prctl(PR_SET_PDEATHSIG), which sends a signal when the parent process exits. Sounds perfect, BUT -- the way ssh-pageant (or any similar daemon) forks into the background means that its parent is actually the initial pre-forked process, which exits after printing the environment variables. So after that the background process is always running as an orphan with parent 1, as you can see from ps.

It might be possible for it to remember the parent PID from the pre-fork process, or as you say take a PID in a command line option, but I'm not sure how to wait for a PID that's not your own parent or immediate child. At least there's nothing I know of in posix/cygwin APIs, but perhaps there's a Windows API for this? Not sure. I'd really prefer to avoid polling though, so hopefully the solution would either be via a signal or a handle I can add to the select loop.

Yet another way to handle this is to arrange for the shell to be invoked as ssh-pageant's child. In this case, ssh-pageant does not daemonize, and it exits cleanly as soon as SIGCHLD indicates that the child process terminated. So for example, if you're using mintty, you could just change the shortcut to run "mintty /usr/bin/ssh-pageant /bin/bash -l" to get a login shell as a child of ssh-pageant.

I don't think there would be much value in adding an option to kill other ssh-pageants into ssh-pageant itself. This is something that can just as well be done from the outside, sending any of SIGHUP, SIGKILL, or SIGTERM, and the process will react by cleaning up its socket and exiting. So for instance, if you want to only have one fresh ssh-pageant, just run "killall ssh-pageant" before starting the new one. Or if you're somehow determining a list of PIDs that you want to keep, just use that same knowledge to send signals to the rest.

As for your normal cleanup strategy, are you sure that trap EXIT runs when when the shell terminates on a signal? I think it doesn't. The way I have it myself is that I only start ssh-pageant in login shells via .bash_profile, and I do the cleanup in .bash_logout which runs as login shells exit. Then my "trap logout HUP" makes it also run the logout script on a SIGHUP, which is sent for example by mintty when I close the window.

Whew, didn't mean to write such a long essay on this topic, but even if no solution is added to ssh-pageant itself, hopefully this is still useful to document the options.

Thanks for the insight. Sorry about the confusing terms, orphans is what I did mean for sure.

I had originally only thought of using polling, which is why I'd suggested a polling interval of 3-5 minutes for a single check, but then, I don't actually know how annoying that is to do ;).

The start-as-child thing works perfectly for me. I'm still using the cmd based bash, so I just stuck C:\cygwin\bin\ssh-pageant.exe in front of it and it works fine. I don't think I realized the program would take a shell as a child.

I don't know about the cleanup strategy. I had gotten myself to thinking that the .bash_logout file was only actually invoked by your trap, but I may have missed something in the vast bash docs ;). Don't need cleanup with the new method anyhow.

Ok, since you're now happy, I'm closing this bug. If someday I can figure out a non-polling method to watch arbitrary PIDs, that may still be a useful enhancement, but not today because I'm feeling lazy. :)