[libvirt] PATCH: 17/25: Concurrent client dispatch in libvirtd

Daniel P. Berrange berrange at redhat.com
Tue Jan 20 10:27:56 UTC 2009


On Tue, Jan 20, 2009 at 10:12:04AM +0100, Jim Meyering wrote:
> >      } else {
> >          ret = gnutls_record_recv (client->tlssession, data, len);
> > -        if (qemudRegisterClientEvent (server, client, 1) < 0)
> > -            qemudDispatchClientFailure (server, client);
> > -        else if (ret <= 0) {
> > -            if (ret == 0 || (ret != GNUTLS_E_AGAIN &&
> > -                             ret != GNUTLS_E_INTERRUPTED)) {
> > -                if (ret != 0)
> > -                    VIR_ERROR(_("gnutls_record_recv: %s"),
> > -                              gnutls_strerror (ret));
> > -                qemudDispatchClientFailure (server, client);
> > -            }
> > +
> > +        if (ret == -1 && (ret == GNUTLS_E_AGAIN &&
> > +                          ret == GNUTLS_E_INTERRUPTED))
> > +            return 0;
> 
> The above is dead code, since the condition can never be true.
> It should be testing "ret < 0", not ret == -1.
> Also, the 2nd "&&" should be "||".
> 
>            if (ret < 0 && (ret == GNUTLS_E_AGAIN ||
>                            ret == GNUTLS_E_INTERRUPTED))
>                return 0;

Yes, really not sure why I change it like this. Clearly wrong

> >          if (encodedLen < 0)
> >              return -1;
> >
> > -        sasl_decode(client->saslconn, encoded, encodedLen,
> > -                    &client->saslDecoded, &client->saslDecodedLength);
> > +        ret = sasl_decode(client->saslconn, encoded, encodedLen,
> > +                          &client->saslDecoded, &client->saslDecodedLength);
> > +        if (ret != SASL_OK)
> > +            return -1;
> 
> If this ever fails, it's sure be nice to log why,
> but I don't see a strerror analog for SASL_* values.

Actually there are two options sasl_errstring / sasl_errdetail
both giving suitable output.

> > -        if (qemudClientRead(server, client) < 0)
> > -            return; /* Error, or blocking */
> > +        xdrmem_create(&x, client->rx->buffer, client->rx->bufferLength, XDR_DECODE);
> >
> > -        if (client->bufferOffset < client->bufferLength)
> > -            return; /* Not read enough */
> > -
> > -        xdrmem_create(&x, client->buffer, client->bufferLength, XDR_DECODE);
> > -
> > -        if (!xdr_u_int(&x, &len)) {
> > +        if (!xdr_int(&x, &len)) {
> >              xdr_destroy (&x);
> >              DEBUG0("Failed to decode packet length");
> > -            qemudDispatchClientFailure(server, client);
> > +            qemudDispatchClientFailure(client);
> >              return;
> >          }
> >          xdr_destroy (&x);
> >
> > +        /* Length includes the size of the length word itself */
> > +        len -= REMOTE_MESSAGE_HEADER_XDR_LEN;
> > +
> >          if (len > REMOTE_MESSAGE_MAX) {
> >              DEBUG("Packet length %u too large", len);
> > -            qemudDispatchClientFailure(server, client);
> > +            qemudDispatchClientFailure(client);
> >              return;
> >          }
> >
> >          /* Length include length of the length field itself, so
> >           * check minimum size requirements */
> > -        if (len <= REMOTE_MESSAGE_HEADER_XDR_LEN) {
> > +        if (len <= 0) {
> >              DEBUG("Packet length %u too small", len);
> 
> "len" may be negative here, so printing with %u will give a
> misleading diagnostic.
> Better use the original value, "len + REMOTE_MESSAGE_HEADER_XDR_LEN",
> which is more likely to be non-negative.  Might as well use %d,
> in case even the original value is negative.

SOmething odd here - I don't think I should have been changing it
to signed in the first place. The original code used unsigned int
and this is on the wire. Oddly the original client code used a 
signed int, so we had a mis-match of client & server. I think it
is better to fix the client though. So I'll re-visit this whole
chunk

> >
> > -    if (client->fd != fd)
> > -        return;
> > +    if (events & (VIR_EVENT_HANDLE_WRITABLE |
> > +                  VIR_EVENT_HANDLE_READABLE)) {
> > +        if (client->handshake) {
> > +            qemudDispatchClientHandshake(server, client);
> > +        } else {
> > +            if (events & VIR_EVENT_HANDLE_WRITABLE)
> > +                qemudDispatchClientWrite(server, client);
> > +            if (events == VIR_EVENT_HANDLE_READABLE)
> > +                qemudDispatchClientRead(server, client);
> 
> Why test with & to write, and then with "==" to read?
> That makes it so we don't read when we've just written
> (i.e., if both read and write bits were set).

Bug, it should be '&' and not '=='.

> > diff --git a/qemud/qemud.h b/qemud/qemud.h
> ...
> > +struct qemud_client_message {
> ...
> > +    int nrequests;
> 
> Logically, this should be an unsigned type.
> But that means max_clients should be, too,
> since they're compared, but max_clients comes
> from the config file, which currently uses "int" (via GET_CONF_INT).
> Maybe we need GET_CONF_UINT?  I wonder if a bogus config "int"
> value of 2^32 or 2^64 maps back to 0.

Checking for 2^32/64 is not really helpful in this context, because both
are totally inappropriate for nrequests - we should check for a more
reasonable lower limit on nrequests, perhaps in range 1 -> 100.

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list