[libvirt] [PATCH] virCommand: Properly handle POLLHUP

Michal Privoznik mprivozn at redhat.com
Wed Jan 4 09:36:27 UTC 2012


On 03.01.2012 20:09, Daniel P. Berrange wrote:
> On Tue, Jan 03, 2012 at 06:58:51PM +0100, Michal Privoznik wrote:
>> It is a good practise to set revents to zero before doing any poll().
>> Moreover, we should check if event we waited for really occurred or
>> if any of fds we were polling on didn't encountered hangup.
>> ---
>>  src/util/command.c |   21 +++++++++++++++++----
>>  1 files changed, 17 insertions(+), 4 deletions(-)
>>
>> diff --git a/src/util/command.c b/src/util/command.c
>> index f5effdf..9b553f0 100644
>> --- a/src/util/command.c
>> +++ b/src/util/command.c
>> @@ -1620,16 +1620,19 @@ virCommandProcessIO(virCommandPtr cmd)
>>          if (infd != -1) {
>>              fds[nfds].fd = infd;
>>              fds[nfds].events = POLLOUT;
>> +            fds[nfds].revents = 0;
>>              nfds++;
>>          }
>>          if (outfd != -1) {
>>              fds[nfds].fd = outfd;
>>              fds[nfds].events = POLLIN;
>> +            fds[nfds].revents = 0;
>>              nfds++;
>>          }
>>          if (errfd != -1) {
>>              fds[nfds].fd = errfd;
>>              fds[nfds].events = POLLIN;
>> +            fds[nfds].revents = 0;
>>              nfds++;
>>          }
> 
> ACK to this bit, clearly addressing a bug
> 
> 
>>  
>> @@ -1645,8 +1648,8 @@ virCommandProcessIO(virCommandPtr cmd)
>>          }
>>  
>>          for (i = 0; i < nfds ; i++) {
>> -            if (fds[i].fd == errfd ||
>> -                fds[i].fd == outfd) {
>> +            if (fds[i].revents & POLLIN &&
>> +                (fds[i].fd == errfd || fds[i].fd == outfd)) {
>>                  char data[1024];
>>                  char **buf;
>>                  size_t *len;
>> @@ -1684,7 +1687,7 @@ virCommandProcessIO(virCommandPtr cmd)
>>                      memcpy(*buf + *len, data, done);
>>                      *len += done;
>>                  }
>> -            } else {
>> +            } else if (fds[i].revents & POLLOUT) {
>>                  int done;
>>  
>>                  /* Coverity 5.3.0 can't see that we only get here if
>> @@ -1708,8 +1711,18 @@ virCommandProcessIO(virCommandPtr cmd)
>>                              VIR_DEBUG("ignoring failed close on fd %d", tmpfd);
>>                      }
>>                  }
>> +            } else if (fds[i].revents & POLLHUP) {
>> +                if (fds[i].fd == errfd) {
>> +                    VIR_DEBUG("hangup on stderr");
>> +                    errfd = -1;
>> +                } else if (fds[i].fd == outfd) {
>> +                    VIR_DEBUG("hangup on stdout");
>> +                    outfd = -1;
>> +                } else {
>> +                    VIR_DEBUG("hangup on stdin");
>> +                    infd = -1;
>> +                }
>>              }
> 
> 
> Was this part of the change actually solving anything ?  When you have
> POLLIN set in the events, you'll never get a bare POLLHUP event back
> in revents. You'll always get revents set to POLLIN|POLLHUP. Thus since
> an earlier if() checks for POLLIN, I'm fairly sure this POLLHUP block
> you're adding won't ever run.
Yes it was. Simply reproducible test: remove that else branch and try
running commandtest; You'll get this sequence:

fd: 4 ev: 1 rev: 0
fd: 6 ev: 1 rev: 1
fd: 4 ev: 1 rev: 16
fd: 6 ev: 1 rev: 16

diff --git a/src/util/command.c b/src/util/command.c
index 1b62319..22b9d54 100644
--- a/src/util/command.c
+++ b/src/util/command.c
@@ -1648,6 +1648,7 @@ virCommandProcessIO(virCommandPtr cmd)
         }

         for (i = 0; i < nfds ; i++) {
+            printf("fd: %d ev: %d rev: %d\n", fds[i].fd, fds[i].events,
fds[i].revents);
             if (fds[i].revents & POLLIN &&
                 (fds[i].fd == errfd || fds[i].fd == outfd)) {
                 char data[1024];

Although, I agree that POLLHUP semantics is not good documented, to say
the least.
> 
> If we want to explicitly check events for comprehensively, then I
> think we'd want to avoid the if/elseif/elseif style, and use separate
> if/if/if tests for each POLLXXX bit.
Okay, I'll go this way.

> 
> Regards,
> Daniel




More information about the libvir-list mailing list