From ba968f2161ffb4e936c283487249ea28601964c4 Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Fri, 26 Jun 2020 19:00:05 +0200 Subject: use blocking/nonblocking reads instead of poll(2) Previously, we used a blocking fd for the token pipe and used poll(2) to see if anything could be read right now in try_procure(). However, there is a race between poll(2) and the subsequent blocking read(2), which can result in processes deadlocking when multiple instances of redo poll at the same time. Instead, we now make the fd nonblocking when needed, so that the read either reads or returns immediately if there is nothing to read. Closes #3. Closes: #4 [via git-merge-pr] --- redo.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/redo.c b/redo.c index f482023..ad8b156 100644 --- a/redo.c +++ b/redo.c @@ -34,7 +34,6 @@ todo: #include #include #include -#include #include #include #include @@ -739,19 +738,13 @@ try_procure() implicit_jobs--; return 1; } else { - struct pollfd p; - if (poolrd_fd < 0) return 0; - p.fd = poolrd_fd; - p.events = POLLIN; + fcntl(poolrd_fd, F_SETFL, O_NONBLOCK); - if (poll(&p, 1, 0) > 0 && p.revents & POLLIN) { - char buf[1]; - return read(poolrd_fd, &buf, 1) > 0; - } - return 0; + char buf[1]; + return read(poolrd_fd, &buf, 1) > 0; } } @@ -762,6 +755,8 @@ procure() implicit_jobs--; return 1; } else { + fcntl(poolrd_fd, F_SETFL, 0); // clear O_NONBLOCK + char buf[1]; return read(poolrd_fd, &buf, 1) > 0; } -- cgit 1.4.1