[Xcb] [PATCH libxcb 4/4] send_fds(): Handle too many outstanding requests
Ran Benita
ran234 at gmail.com
Sat May 16 07:16:26 PDT 2015
On Thu, May 14, 2015 at 09:55:35AM +0200, Uli Schlachter wrote:
> Before this patch, the following code caused an endless loop in send_fds(),
> because the queue of FDs to send was eventually full, but _xcb_out_flush_to()
> didn't make any progress, since there was no FD to send:
>
> while (1) { xcb_send_fd(conn, dup(some_fd)); }
>
> Fix this by sending a sync when flushing didn't make any progress. That way we
> actually have something to send and can attach the pending FDs.
>
> Because send_fds() can now send requests, the code in
> xcb_send_request_with_fds64() has to be changed. It has to call send_fds()
> before it establishes a good sequence number for the request it wants to send.
I think I'm really misunderstanding here, so feel free to ignore.
But fds are associated with a specific request (and are sent as
ancillary data with the request itself). So sending a *dummy* request to
clear up the fds buffer seems really strange - what about the original
request they were intended for?
I don't really understand why the fds array of a request can't just be
kept along with it in whatever queue xcb keeps, then there's no need for
synchronization. With your new combined send_request_with_fds(), it seems
possible to make it so that the request and the fds flow together to the
eventual sendmsg().
I guess xcb_send_fd() still needs to use the shared fds buffer by design,
but can't it just be removed? After all we don't support using
libxcb-foo.so without the exact matching version of libxcb.so. Or is it
considered public API?
Ran
>
> Signed-off-by: Uli Schlachter <psychon at znc.in>
> ---
> src/xcb_out.c | 16 +++++++++++++---
> 1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/src/xcb_out.c b/src/xcb_out.c
> index 06fae4c..37fd16d 100644
> --- a/src/xcb_out.c
> +++ b/src/xcb_out.c
> @@ -187,11 +187,17 @@ static void send_fds(xcb_connection_t *c, unsigned int num_fds, int *fds)
> {
> #if HAVE_SENDMSG
> while (num_fds > 0) {
> - /* FIXME: This will busy-loop when XCB_MAX_PASS_FD fds are sent at once */
> while (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
> _xcb_out_flush_to(c, c->out.request);
> if (c->has_error)
> break;
> +
> + if (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
> + /* We need some request to send FDs with */
> + _xcb_out_send_sync(c);
> + if (c->has_error)
> + break;
> + }
> }
> if (!c->has_error)
> c->out.out_fd.fd[c->out.out_fd.nfd++] = fds[0];
> @@ -296,6 +302,11 @@ uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iove
> /* get a sequence number and arrange for delivery. */
> pthread_mutex_lock(&c->iolock);
>
> + /* send FDs before establishing a good request number, because this might
> + * call send_sync(), too
> + */
> + send_fds(c, num_fds, fds);
> +
> prepare_socket_request(c);
>
> /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
> @@ -304,7 +315,7 @@ uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iove
> * applications see sequence 0 as that is used to indicate
> * an error in sending the request
> */
> -
> +
> while ((req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) ||
> (unsigned int) (c->out.request + 1) == 0)
> {
> @@ -312,7 +323,6 @@ uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iove
> prepare_socket_request(c);
> }
>
> - send_fds(c, num_fds, fds);
> send_request(c, req->isvoid, workaround, flags, vector, veclen);
> request = c->has_error ? 0 : c->out.request;
> pthread_mutex_unlock(&c->iolock);
> --
> 2.1.4
>
> _______________________________________________
> Xcb mailing list
> Xcb at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xcb
More information about the Xcb
mailing list