diff --git a/include/dixstruct.h b/include/dixstruct.h index 7711cde99..456e63360 100644 --- a/include/dixstruct.h +++ b/include/dixstruct.h @@ -110,8 +110,16 @@ typedef struct _Client { DeviceIntPtr clientPtr; ClientIdPtr clientIds; + int req_fds; } ClientRec; +static inline void +SetReqFds(ClientPtr client, int req_fds) { + if (client->req_fds != 0 && req_fds != client->req_fds) + LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", req_fds, client->req_fds); + client->req_fds = req_fds; +} + /* * Scheduling interface */ diff --git a/include/os.h b/include/os.h index 3840ab911..b654a0d45 100644 --- a/include/os.h +++ b/include/os.h @@ -98,6 +98,8 @@ extern _X_EXPORT int WaitForSomething(int * /*pClientsReady */ extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ ); +extern _X_EXPORT int ReadFdFromClient(ClientPtr client); + extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ , char * /*data */ , int /*count */ ); diff --git a/os/io.c b/os/io.c index 380036664..83df6e9b0 100644 --- a/os/io.c +++ b/os/io.c @@ -259,6 +259,12 @@ ReadRequestFromClient(ClientPtr client) oc->input = oci; } + /* Discard any unused file descriptors */ + while (client->req_fds > 0) { + int req_fd = ReadFdFromClient(client); + if (req_fd >= 0) + close(req_fd); + } /* advance to start of next request */ oci->bufptr += oci->lenLastReq; @@ -485,6 +491,21 @@ ReadRequestFromClient(ClientPtr client) return needed; } +int +ReadFdFromClient(ClientPtr client) +{ + int fd = -1; + + if (client->req_fds > 0) { + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + --client->req_fds; + fd = _XSERVTransRecvFd(oc->trans_conn); + } else + LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n"); + return fd; +} + /***************************************************************** * InsertFakeRequest * Splice a consed up (possibly partial) request in as the next request.