about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2020-06-26 19:00:05 +0200
committerLeah Neukirchen <leah@vuxu.org>2020-06-26 23:46:40 +0200
commitba968f2161ffb4e936c283487249ea28601964c4 (patch)
tree2c44585d978dfd1baace908ccd8636df5729ee3c
parent7013b5e384b74bc425f10c88b6f78e3a7a4fd39e (diff)
downloadredo-c-ba968f2161ffb4e936c283487249ea28601964c4.tar.gz
redo-c-ba968f2161ffb4e936c283487249ea28601964c4.tar.xz
redo-c-ba968f2161ffb4e936c283487249ea28601964c4.zip
use blocking/nonblocking reads instead of poll(2) v0.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]
-rw-r--r--redo.c15
1 files 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 <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <poll.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -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;
 	}