[libvirt] [PATCH] Re-write LXC controller end-of-file I/O handling yet again

Eric Blake eblake at redhat.com
Thu Jan 12 19:56:23 UTC 2012


On 01/12/2012 10:20 AM, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 
> Currently the LXC controller attempts to deal with EOF on a
> tty by spawning a thread todo a edge triggered epoll_wait().

s/todo a edge /to do an edge-/

> This avoids the normal event loop spinning on POLLHUP. There
> is a subtle mistake though - even after seeing POLLHUP on a
> master PTY, it is still perfectly possible & valid to write
> data to the PTY. There is a buffer that can be filled with
> data, even when no client is present.
> 
> The second mistake is that the epoll_wait() thread was not
> looking for the EPOLLOUT condition, so when a new client
> connects to the LXC console, it had to explicitly send a
> character before any queued output would appear.
> 
> Finally, there was in fact no need to spawn a new thread to
> deal with epoll_wait(). The epoll file descriptor itself
> can be poll()'d on normally.
> 
> This patch attempts to deal with all these problems.
> 
>  - The blocking epoll_wait() thread is replaced by a poll
>    on the epoll file descriptor which then does a non-blocking
>    epoll_wait() to handle events
>  - Even if POLLHUP is seen, we continue trying to write
>    any pending output until getting EAGAIN from write.
>  - Once write returns EAGAIN, we modify the epoll event
>    mask to also look for EPOLLOUT

The description makes sense; now on to the code :)

> +    } else if (console->hostEpoll) {
> +        VIR_DEBUG("Stop epoll oldContEvents=%x", console->hostEpoll);
> +        if (epoll_ctl(console->epollFd, EPOLL_CTL_DEL, console->hostFd, NULL) < 0) {
> +            virReportSystemError(errno, "%s",
> +                                 _("Unable to add epoll fd"));

s/add/remove/ in the error message

> +    } else if (console->contEpoll) {
> +        VIR_DEBUG("Stop epoll oldContEvents=%x", console->contEpoll);
> +        if (epoll_ctl(console->epollFd, EPOLL_CTL_DEL, console->contFd, NULL) < 0) {
> +            virReportSystemError(errno, "%s",
> +                                 _("Unable to add epoll fd"));

And again.

> @@ -1103,9 +1163,32 @@ static int lxcControllerMain(int serverFd,
>      }
>  
>      for (i = 0 ; i < nFds ; i++) {
> +        consoles[i].epollFd = -1;
> +        consoles[i].epollFd = -1;

Why do you have this line twice?  Did you mean to initialize epollWatch
instead?

> +        consoles[i].hostWatch = -1;
> +        consoles[i].contWatch = -1;
> +    }
> +
> +    for (i = 0 ; i < nFds ; i++) {
>          consoles[i].hostFd = hostFds[i];
>          consoles[i].contFd = contFds[i];
>  
> +        if ((consoles[i].epollFd = epoll_create(2)) < 0) {

Should we be using epoll_create1(EPOLL_CLOEXEC)?

Overall, it looks fairly clean; I'm assuming that you actually tested
with it, and I didn't hit any compilation errors.  And the man page for
poll definitely recommends that you must plow on until EAGAIN if you use
EPOLLET, so this new code certainly looks cleaner in that regards.

I'm okay giving ACK with nits fixed.

-- 
Eric Blake   eblake at redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 620 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20120112/81f4d5d0/attachment-0001.sig>


More information about the libvir-list mailing list