keithw/mosh — pull request #221 by saurik (2012-04-18 23:20:51+00:00)
Title: OS X has a race condition establishing your security session

On OS X, due to the way security sessions and bootstrap Mach contexts (I'm honestly not 100% certain which is the problem here, and my understanding of these systems is not perfect: it mostly comes from working on the new Substrate injector from a few months ago, and some work I did on absinthe) are inherited, if sshd shuts down before the login shell starts up (which both can happen and normally does happen as the parent mosh-server does an _exit *immediately* after a fork, causing that process to exit before the children get very far), then the resulting shell is pretty much entirely broken: you can't even figure out your own username (whoami returns numbers and bash simply prints "I have no name!"), much less talk to complex Mach services such as launchd.

The patch referenced by this pull request is obviously stupid and non-deterministic (it is just a call to sleep(2) before the _exit() after the fork() in the parent mosh-server process), but at least it demonstrates the problem and is a starting point for people looking at this problem to figure out a better way to handle it (or for those experiencing it, such as @jcftang from #218) to find temporary relief.

Obviously, however, the final fix needs to be deterministic. The problem, though, is I'm not certain how long we really need to wait; do we just need to wait for the second fork, for the second psuedo-terminal to be created, for the login shell to actually "do something"... I don't know (although my current bet is that if we coordinate such that after the second fork, which also happens to create the pseudo-terminal anyway as it is really a call to forkpty, we'll be golden).

Doing that will require some irritating synchronization primitive between the various processes (and in the worse case something like waiting for the terminal to actually bear fruit, which would require the terminal network loop to get involved). Anyone doing that should also try to verify (maybe by adding a long sleep in the child after the synchronization) that the event being waited for is actually truly sufficient (and not just probabilistically better).

(There are other solutions--ones that involve changing the way OpenSSH and mosh get bootstrapped together--that may also provide better fixes for other bugs, but those are more drastic and against some of the goals of the project developers; they are probably even pragmatically wrong anyway, as there actually are some key advantages to this OpenSSH->mosh-server craziness, although those may be short-term.)