common: add bt_common_read() function
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Fri, 3 May 2019 19:11:00 +0000 (15:11 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 3 May 2019 23:04:25 +0000 (19:04 -0400)
This function wraps the `read()` function to handle EINTR and partial
reads.

It returns the `count` value on success, or a smaller value than `count`
on error.

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Change-Id: Ib0385855447200d97a58da704dcf68423e857033
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1248
Reviewed-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
include/babeltrace/common-internal.h

index 0e84e8fa49007b706e1214195cb1507e14a34eb1..19594fe3c347f4345788befe9078df3dac13bcf2 100644 (file)
 #include <babeltrace/trace-ir/event-class-const.h>
 #include <babeltrace/graph/self-message-iterator.h>
 #include <babeltrace/value.h>
-#include <stdarg.h>
 #include <inttypes.h>
+#include <stdarg.h>
 #include <stdint.h>
+#include <unistd.h>
 #include <glib.h>
 
 #define BT_COMMON_COLOR_RESET              "\033[0m"
@@ -305,6 +306,55 @@ void bt_common_custom_snprintf(char *buf, size_t buf_size,
 BT_HIDDEN
 size_t bt_common_get_page_size(void);
 
+/*
+ * Wraps read() function to handle EINTR and partial reads.
+ * On success, it returns `count` received as parameter. On error, it returns a
+ * value smaller than the requested `count`.
+ */
+static inline
+ssize_t bt_common_read(int fd, void *buf, size_t count)
+{
+       size_t i = 0;
+       ssize_t ret;
+
+       BT_ASSERT(buf);
+
+       /* Never return an overflow value. */
+       BT_ASSERT(count <= SSIZE_MAX);
+
+       do {
+               ret = read(fd, buf + i, count - i);
+               if (ret < 0) {
+                       if (errno == EINTR) {
+#ifdef BT_LOGD_STR
+                               BT_LOGD_STR("read() call interrupted. Retrying...");
+#endif
+                               /* retry operation */
+                               continue;
+                       } else {
+#ifdef BT_LOGE_ERRNO
+                               BT_LOGE_ERRNO("Error while reading", ": fd=%d",
+                                       fd);
+#endif
+                               goto end;
+                       }
+               }
+               i += ret;
+               BT_ASSERT(i <= count);
+       } while (count - i > 0 && ret > 0);
+
+end:
+       if (ret >= 0) {
+               if (i == 0) {
+                       ret = -1;
+               } else {
+                       ret = i;
+               }
+       }
+
+       return ret;
+}
+
 static inline
 const char *bt_common_field_class_type_string(enum bt_field_class_type class_type)
 {
This page took 0.025511 seconds and 4 git commands to generate.