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

Paul Corke paul.corke at datatote.co.uk
Tue Nov 11 11:18:35 CET 2008


There appears to be a bug in vlc's httpd server.

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/b29047f7/attachment.obj>


More information about the vlc-devel mailing list