From b6d7ed4d787a652e8150532f384bfdf51760f3c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Nov 2013 22:12:34 -0800 Subject: [PATCH] miext: Move SyncShm FDs out of the way of clients Applications may end up allocating a bunch of shmfence objects, each of which uses a file descriptor, which must be kept open lest some other client ask for a copy of it later on. Lacking an API that can turn a memory mapping back into a file descriptor, about the best we can do is push the file descriptors out of the way of other X clients so that we don't run out of the ability to accept new connections. This uses fcntl F_GETFD to push the FD up above MAXCLIENTS. Signed-off-by: Keith Packard Reviewed-by: Julien Cristau --- include/os.h | 3 +++ miext/sync/misyncshm.c | 3 +++ os/utils.c | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/include/os.h b/include/os.h index 450e1a8e8..9b6729421 100644 --- a/include/os.h +++ b/include/os.h @@ -686,4 +686,7 @@ LogPrintMarkers(void); extern _X_EXPORT void xorg_backtrace(void); +extern _X_EXPORT int +os_move_fd(int fd); + #endif /* OS_H */ diff --git a/miext/sync/misyncshm.c b/miext/sync/misyncshm.c index 3f9350af5..20780fde8 100644 --- a/miext/sync/misyncshm.c +++ b/miext/sync/misyncshm.c @@ -32,6 +32,7 @@ #include "pixmapstr.h" #include #include +#include #include static DevPrivateKeyRec syncShmFencePrivateKey; @@ -126,6 +127,7 @@ miSyncShmCreateFenceFromFd(ScreenPtr pScreen, SyncFence *pFence, int fd, Bool in miSyncInitFence(pScreen, pFence, initially_triggered); + fd = os_move_fd(fd); pPriv->fence = xshmfence_map_shm(fd); if (pPriv->fence) { pPriv->fd = fd; @@ -145,6 +147,7 @@ miSyncShmGetFenceFd(ScreenPtr pScreen, SyncFence *pFence) pPriv->fd = xshmfence_alloc_shm(); if (pPriv->fd < 0) return -1; + pPriv->fd = os_move_fd(pPriv->fd); pPriv->fence = xshmfence_map_shm(pPriv->fd); if (!pPriv->fence) { close (pPriv->fd); diff --git a/os/utils.c b/os/utils.c index fb20da755..608ee6ab0 100644 --- a/os/utils.c +++ b/os/utils.c @@ -2071,3 +2071,27 @@ FormatUInt64Hex(uint64_t num, char *string) string[len] = '\0'; } + +/* Move a file descriptor out of the way of our select mask; this + * is useful for file descriptors which will never appear in the + * select mask to avoid reducing the number of clients that can + * connect to the server + */ +int +os_move_fd(int fd) +{ + int newfd; + +#ifdef F_DUPFD_CLOEXEC + newfd = fcntl(fd, F_DUPFD_CLOEXEC, MAXCLIENTS); +#else + newfd = fcntl(fd, F_DUPFD, MAXCLIENTS); +#endif + if (newfd < 0) + return fd; +#ifndef F_DUPFD_CLOEXEC + fcntl(newfd, F_SETFD, FD_CLOEXEC); +#endif + close(fd); + return newfd; +}