From 55ca93469cfaa5ca1d9b6e4c164b23ef55763eb5 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 7 Aug 2021 13:46:38 +0200 Subject: util/shm: add allocate_shm_file_pair This function behaves like allocate_shm_file, except it also returns a read-only FD. This is useful to share the same segment of memory with many Wayland clients. --- util/shm.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'util') diff --git a/util/shm.c b/util/shm.c index f7c7303e..e0d84e8e 100644 --- a/util/shm.c +++ b/util/shm.c @@ -8,6 +8,8 @@ #include #include "util/shm.h" +#define RANDNAME_PATTERN "/wlroots-XXXXXX" + static void randname(char *buf) { struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); @@ -18,17 +20,15 @@ static void randname(char *buf) { } } -int create_shm_file(void) { +static int excl_shm_open(char *name) { int retries = 100; do { - char name[] = "/wlroots-XXXXXX"; - randname(name + strlen(name) - 6); + randname(name + strlen(RANDNAME_PATTERN) - 6); --retries; // CLOEXEC is guaranteed to be set by shm_open int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); if (fd >= 0) { - shm_unlink(name); return fd; } } while (retries > 0 && errno == EEXIST); @@ -37,10 +37,12 @@ int create_shm_file(void) { } int allocate_shm_file(size_t size) { - int fd = create_shm_file(); + char name[] = RANDNAME_PATTERN; + int fd = excl_shm_open(name); if (fd < 0) { return -1; } + shm_unlink(name); int ret; do { @@ -53,3 +55,35 @@ int allocate_shm_file(size_t size) { return fd; } + +bool allocate_shm_file_pair(size_t size, int *rw_fd_ptr, int *ro_fd_ptr) { + char name[] = RANDNAME_PATTERN; + int rw_fd = excl_shm_open(name); + if (rw_fd < 0) { + return false; + } + + // CLOEXEC is guaranteed to be set by shm_open + int ro_fd = shm_open(name, O_RDONLY, 0); + if (ro_fd < 0) { + shm_unlink(name); + close(rw_fd); + return false; + } + + shm_unlink(name); + + int ret; + do { + ret = ftruncate(rw_fd, size); + } while (ret < 0 && errno == EINTR); + if (ret < 0) { + close(rw_fd); + close(ro_fd); + return false; + } + + *rw_fd_ptr = rw_fd; + *ro_fd_ptr = ro_fd; + return true; +} -- cgit v1.2.3