(submit/recv-fds) os: read file descriptors into client struct at once

Instead of having the request handler ask for fd's one by one, just read them
all into a little array in ClientRec struct. And also automatically clean up
after request had been handled.

Request handlers need to set the entries to -1 if they shouldn't be closed
automatically.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
Enrico Weigelt, metux IT consult 2024-07-22 19:43:51 +02:00
parent b487d2d77f
commit 2e847c7b23
7 changed files with 37 additions and 44 deletions

View File

@ -1151,14 +1151,15 @@ ProcShmAttachFd(ClientPtr client)
REQUEST(xShmAttachFdReq);
struct stat statb;
SetReqFds(client, 1);
REQUEST_SIZE_MATCH(xShmAttachFdReq);
LEGAL_NEW_RESOURCE(stuff->shmseg, client);
if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
client->errorValue = stuff->readOnly;
return BadValue;
}
fd = ReadFdFromClient(client);
fd = client->recv_fd_list[0];
client->recv_fd_list[0] = -1;
if (fd < 0)
return BadMatch;
@ -1462,7 +1463,6 @@ static int _X_COLD
SProcShmAttachFd(ClientPtr client)
{
REQUEST(xShmAttachFdReq);
SetReqFds(client, 1);
REQUEST_SIZE_MATCH(xShmAttachFdReq);
swapl(&stuff->shmseg);
return ProcShmAttachFd(client);

View File

@ -562,6 +562,14 @@ Dispatch(void)
(*client->requestVector[client->majorOp]) (client);
currentClient = NULL;
}
#if XTRANS_SEND_FDS
/* close down all unused passed fd's */
for (int x=0; x<MAX_CLIENT_RECV_FD; x++) {
close(client->recv_fd_list[x]);
client->recv_fd_list[x] = -1;
}
#endif
}
if (!SmartScheduleSignalEnable)
SmartScheduleTime = GetTimeInMillis();

View File

@ -16,13 +16,6 @@
#include "dixstruct.h"
#include <X11/Xmd.h>
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
*/

View File

@ -191,7 +191,6 @@ proc_dri3_pixmap_from_buffer(ClientPtr client)
CARD32 stride, offset;
int rc;
SetReqFds(client, 1);
REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
LEGAL_NEW_RESOURCE(stuff->pixmap, client);
rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
@ -220,7 +219,8 @@ proc_dri3_pixmap_from_buffer(ClientPtr client)
}
}
fd = ReadFdFromClient(client);
fd = client->recv_fd_list[0];
client->recv_fd_list[0] = -1;
if (fd < 0)
return BadValue;
@ -309,7 +309,6 @@ proc_dri3_fence_from_fd(ClientPtr client)
int fd;
int status;
SetReqFds(client, 1);
REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
LEGAL_NEW_RESOURCE(stuff->fence, client);
@ -317,7 +316,8 @@ proc_dri3_fence_from_fd(ClientPtr client)
if (status != Success)
return status;
fd = ReadFdFromClient(client);
fd = client->recv_fd_list[0];
client->recv_fd_list[0] = -1;
if (fd < 0)
return BadValue;
@ -434,7 +434,6 @@ proc_dri3_pixmap_from_buffers(ClientPtr client)
int rc;
int i;
SetReqFds(client, stuff->num_buffers);
REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq);
LEGAL_NEW_RESOURCE(stuff->pixmap, client);
rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
@ -470,7 +469,7 @@ proc_dri3_pixmap_from_buffers(ClientPtr client)
}
for (i = 0; i < stuff->num_buffers; i++) {
fds[i] = ReadFdFromClient(client);
fds[i] = client->recv_fd_list[i];
if (fds[i] < 0) {
while (--i >= 0)
close(fds[i]);
@ -609,7 +608,6 @@ proc_dri3_import_syncobj(ClientPtr client)
int fd;
int status;
SetReqFds(client, 1);
REQUEST_SIZE_MATCH(xDRI3ImportSyncobjReq);
LEGAL_NEW_RESOURCE(stuff->syncobj, client);
@ -620,7 +618,8 @@ proc_dri3_import_syncobj(ClientPtr client)
screen = drawable->pScreen;
fd = ReadFdFromClient(client);
fd = client->recv_fd_list[0];
client->recv_fd_list[0] = -1;
if (fd < 0)
return BadValue;

View File

@ -73,6 +73,9 @@ typedef struct _saveSet {
#define SaveSetAssignToRoot(ss,tr) ((ss).toRoot = (tr))
#define SaveSetAssignMap(ss,m) ((ss).map = (m))
/* currently largest one in use is 4 */
#define MAX_CLIENT_RECV_FD 8
typedef struct _Client {
void *requestBuffer;
void *osPrivate; /* for OS layer, including scheduler */
@ -110,7 +113,9 @@ typedef struct _Client {
DeviceIntPtr clientPtr;
ClientIdPtr clientIds;
int req_fds;
int recv_fd_count;
int recv_fd_list[MAX_CLIENT_RECV_FD];
} ClientRec;
typedef struct _WorkQueue {

View File

@ -86,8 +86,6 @@ typedef struct _NewClientRec *NewClientPtr;
extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close);
extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,

36
os/io.c
View File

@ -254,14 +254,6 @@ ReadRequestFromClient(ClientPtr client)
oc->input = oci;
}
#if XTRANS_SEND_FDS
/* Discard any unused file descriptors */
while (client->req_fds > 0) {
int req_fd = ReadFdFromClient(client);
if (req_fd >= 0)
close(req_fd);
}
#endif
/* advance to start of next request */
oci->bufptr += oci->lenLastReq;
@ -461,25 +453,23 @@ ReadRequestFromClient(ClientPtr client)
client->index, req->reqType, req->data, req->length);
}
#endif
return needed;
}
int
ReadFdFromClient(ClientPtr client)
{
int fd = -1;
/* read the passed fds into Client struct */
client->recv_fd_count = 0;
#if XTRANS_SEND_FDS
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");
for (;((client->recv_fd_count < MAX_CLIENT_RECV_FD) &&
(client->recv_fd_list[client->recv_fd_count] = _XSERVTransRecvFd(oc->trans_conn)) > 0);
client->recv_fd_count++) {}
// just in case somebody sent a massive number of fd's
int _fd = -1;
while ((_fd = _XSERVTransRecvFd(oc->trans_conn)) > 0)
close(_fd);
#endif
return fd;
for (int x=client->recv_fd_count; x<MAX_CLIENT_RECV_FD; x++)
client->recv_fd_list[x] = -1;
return needed;
}
int