On 10/13/2011 09:47 AM, Eric Blake wrote:
On 10/12/2011 08:31 PM, Serge E. Hallyn wrote:
> glibc's grantpt and ptsname cannot be used on a fd for a pty not in
> /dev/pts. The lxc controller tries to do just that. So if you try to
> start a container on a system where /dev/pts/0 is not available, it
> will fail. You can make this happen by opening a terminal on
> /dev/pts/0, and doing 'sleep 2h& disown; exit'. To fix this, I call
> the virFileOpenTtyAt() from a forked task in a new mount ns, and first
> mount the container's /dev/pts onto /dev/pts. (Then the opened fd must
> be passed back to the lxc driver). Another solution would be to just
> do it all by hand without grantpt and ptsname.
>
Have you filed a bug against glibc's grantpt?
I should have read your URL, which points to
http://www.cygwin.com/ml/libc-alpha/2011-10/msg00008.html. My
conclusions from that thread are:
We are outside the bounds of POSIX the moment we create a private pts
mount point not located at /dev/pts. Gnulib can't fix the situation for
us (gnulib grantpt is only useful in the context of an application
trying to comply with existing POSIX rules, and cloning/unsharing
namespaces to create a private pts is not in scope for gnulib). So I
don't see that anything is worth reporting to gnulib after all.
Now, after reading more of the code, I see that src/util/util.c exports
virFileOpenTty(), which is hard-coded to opening /dev/ptmx (when it
should _really_ be using posix_openpt to be portable to all platforms).
It also provides (but we forgot to export in libvirt_private.syms)
virFileOpenTtyAt, which is Linux-specific in trying to accommodate
alternate mount points for the pts system. Currently, the only clients
for these two functions is lxc; although virFileOpenTty() might be
useful to other clients that aren't doing Linux-specific container games
with the file system.
So the problem at hand is that as soon as you have a private pts, glibc
doesn't interact well with it. That is, virFileOpenTtyAt() is worthless
in that situation. Serge's patch provides a replacement for _just_ the
private pts situation, which uses glibc by forking and bind-mounting the
private pts back into the glibc expectations of /dev/pts, then passing
that fd back to the parent; the alternative solution would be to ditch
glibc interfaces and do the raw ioctl calls on the master pty ourselves.
Since lxc is already Linux-specific, I think that I would favor this
approach as being simpler (that is, completely ditch virFileOpenTtyAt,
and teach lxc to just make the raw ioctl calls instead of using grantpt
and unlockpt, all without forking or passing fds across a socket).
Serge, is this something you can attempt, or should I look into it more?
--
Eric Blake eblake(a)redhat.com +1-801-349-2682
Libvirt virtualization library
http://libvirt.org