about summary refs log tree commit diff
path: root/include/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/common.h')
-rw-r--r--include/common.h50
1 files changed, 50 insertions, 0 deletions
diff --git a/include/common.h b/include/common.h
index 8b21b55f..e8558e24 100644
--- a/include/common.h
+++ b/include/common.h
@@ -29,6 +29,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/time.h>
 #include "types.h"
 #include "stdbool.h"
@@ -390,5 +391,54 @@ static u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
 
 }
 
+/* Wrapper for select() and read(), reading exactly len bytes.
+  Returns the time passed to read.
+  If the wait times out, returns timeout_ms + 1;
+  Returns 0 if an error occurred (fd closed, signal, ...); */
+static inline u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) {
+
+  struct timeval timeout;
+  fd_set         readfds;
+  FD_ZERO(&readfds);
+  FD_SET(fd, &readfds);
+
+  timeout.tv_sec = (timeout_ms / 1000);
+  timeout.tv_usec = (timeout_ms % 1000) * 1000;
+
+  size_t read_total = 0;
+  size_t len_read = 0;
+
+  while (len_read < len) {
+
+    /* set exceptfds as well to return when a child exited/closed the pipe. */
+    int sret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+
+    if (!sret) {
+
+      // printf("Timeout in sret.");
+      return timeout_ms + 1;
+
+    } else if (sret < 0) {
+
+      // perror("sret malloc");
+      // TODO: catch other (errno == EINTR) than ctrl+c?
+      return 0;
+
+    }
+
+    len_read = read(fd, buf + len_read, len - len_read);
+    if (!len_read) { return 0; }
+    read_total += len_read;
+
+  }
+
+  s32 exec_ms =
+      MIN(timeout_ms,
+          ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000)));
+  return exec_ms > 0 ? exec_ms
+                     : 1;  // at least 1 milli must have passed (0 is an error)
+
+}
+
 #endif