[vlc-devel] [Patch] httpd server fault with multiple clients

Paul Corke paul.corke at datatote.co.uk
Tue Nov 11 16:08:28 CET 2008


There appears to be a bug in vlc's http server (network/httpd.c).

When the ufd is prepared before passing to poll(), the offset into it
is only incremented for clients that we actually want an event for
(lines 2429 + 2430):

2064    for(int i_client = 0; i_client < host->i_client; i_client++ )
2065    {
2080        struct pollfd *pufd = ufd + nfd;
2429            if (pufd->events != 0)
2430                nfd++;
2433    }

However, after the poll(), the offset is incremented for every client
(line 2470):

2467        for( int i_client = 0; i_client < host->i_client; i_client++
)
2468        {
2470            const struct pollfd *pufd = &ufd[host->nfd + i_client];
2474            if( cl->fd != pufd->fd )
2475                continue; // we were not waiting for this client
2504        }

This means that if there are >1 clients and there is no need to wait for
an event on the first one, then the cl->fd is never pufd->fd (line 2474)
so any clients that need to read/write won't be serviced, so the poll
will
just continually return immediately.

This causes 100% CPU until the first client goes into the ufd array, and
data starvation for the other clients.

For example with 3 clients:

  (i_client == 0) => (events == 0) /* Don't want to know about this one
*/
  (i_client == 1) => (events != 0)
  (i_clinet == 2) => (events != 0)

When writing:  ufd[host->nfd + 0] = client_1_socket
               ufd[host->nfd + 1] = client_2_socket
               
When reading:  client_0_socket != ufd[host->nfd + 0]
               client_1_socket != ufd[host->nfd + 1]
               client_2_socket != ufd[host->nfd + 2]
               
So none of the functions like httpd_ClientSend() get called for any of
the clients, even though poll() may indicate that 1 or 2 of them need
it.

The enclosed patch fixes this by only incrementing the offset into ufd[]
when an entry is used.  It changes the end of the example above so:

When reading:  client_0_socket != ufd[host->nfd + 0]
               client_1_socket == ufd[host->nfd + 0]
               client_2_socket == ufd[host->nfd + 1]

I hope this all makes sense... let me know if there's something I
haven't
explained properly!

Regards,

Paul.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Correctly-reads-from-ufd-in-the-case-where-there-a.patch
Type: application/octet-stream
Size: 1195 bytes
Desc: 0001-Correctly-reads-from-ufd-in-the-case-where-there-a.patch
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20081111/2abbb4cb/attachment.obj>


More information about the vlc-devel mailing list