aboutsummaryrefslogtreecommitdiffstats
path: root/cursor
diff options
context:
space:
mode:
authorOlivier Fourdan <ofourdan@redhat.com>2022-05-30 09:14:04 +0200
committerSimon Ser <contact@emersion.fr>2022-06-09 19:18:47 +0000
commitdd00220b1ef6a4c823632a02b535b40602bfb8d4 (patch)
tree856b411bf4cd0d11d2985db9bf10aafd7cbb11b6 /cursor
parentbuild: bump to version 1.20.92 for the beta release (diff)
downloadwayland-dd00220b1ef6a4c823632a02b535b40602bfb8d4.tar
wayland-dd00220b1ef6a4c823632a02b535b40602bfb8d4.tar.gz
wayland-dd00220b1ef6a4c823632a02b535b40602bfb8d4.tar.bz2
wayland-dd00220b1ef6a4c823632a02b535b40602bfb8d4.tar.lz
wayland-dd00220b1ef6a4c823632a02b535b40602bfb8d4.tar.xz
wayland-dd00220b1ef6a4c823632a02b535b40602bfb8d4.tar.zst
wayland-dd00220b1ef6a4c823632a02b535b40602bfb8d4.zip
cursor/os-compatibility: handle EINTR gracefully
If os_resize_anonymous_file() called from os_create_anonymous_file() fails with EINTR (Interrupted system call), then the buffer allocation fails. To avoid that, retry posix_fallocate() on EINTR. However, in the presence of an alarm, the interrupt may trigger repeatedly and prevent a large posix_fallocate() to ever complete successfully, so we need to first block SIGALRM to prevent this. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Diffstat (limited to 'cursor')
-rw-r--r--cursor/os-compatibility.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/cursor/os-compatibility.c b/cursor/os-compatibility.c
index 07452a5..f2445ce 100644
--- a/cursor/os-compatibility.c
+++ b/cursor/os-compatibility.c
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -168,11 +169,28 @@ int
os_resize_anonymous_file(int fd, off_t size)
{
#ifdef HAVE_POSIX_FALLOCATE
+ sigset_t mask;
+ sigset_t old_mask;
+
+ /*
+ * posix_fallocate() might be interrupted, so we need to check
+ * for EINTR and retry in that case.
+ * However, in the presence of an alarm, the interrupt may trigger
+ * repeatedly and prevent a large posix_fallocate() to ever complete
+ * successfully, so we need to first block SIGALRM to prevent
+ * this.
+ */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGALRM);
+ sigprocmask(SIG_BLOCK, &mask, &old_mask);
/*
- * Filesystems that do support fallocate will return EINVAL or
+ * Filesystems that do not support fallocate will return EINVAL or
* EOPNOTSUPP. In this case we need to fall back to ftruncate
*/
- errno = posix_fallocate(fd, 0, size);
+ do {
+ errno = posix_fallocate(fd, 0, size);
+ } while (errno == EINTR);
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
if (errno == 0)
return 0;
else if (errno != EINVAL && errno != EOPNOTSUPP)