libmemif: Add memif_cancel_poll_event() + bug fixing.

Change-Id: I27d6bf93216f1f639f01fad730506afdc7115e46
Signed-off-by: Milan Lenco <milan.lenco@pantheon.tech>
diff --git a/extras/libmemif/src/main.c b/extras/libmemif/src/main.c
index 8cc0d66..b1176c6 100644
--- a/extras/libmemif/src/main.c
+++ b/extras/libmemif/src/main.c
@@ -54,17 +54,18 @@
 /* private structs and functions */
 #include <memif_private.h>
 
-#define ERRLIST_LEN 36
+#define ERRLIST_LEN 37
 #define MAX_ERRBUF_LEN 256
 
 #if __x86_x64__
 #define MEMIF_MEMORY_BARRIER() __builtin_ia32_sfence ()
 #else
-#define MEMIF_MEORY_BARRIER() __sync_synchronize ()
+#define MEMIF_MEMORY_BARRIER() __sync_synchronize ()
 #endif /* __x86_x64__ */
 
 libmemif_main_t libmemif_main;
 int memif_epfd;
+int poll_cancel_fd = -1;
 
 static char memif_buf[MAX_ERRBUF_LEN];
 
@@ -139,7 +140,9 @@
   /* MEMIF_ERR_DISCONNECTED */
   "Interface is disconnected.",
   /* MEMIF_ERR_UNKNOWN_MSG */
-  "Unknown message type received on control channel. (internal error)"
+  "Unknown message type received on control channel. (internal error)",
+  /* MEMIF_ERR_POLL_CANCEL */
+  "Memif event polling was canceled."
 };
 
 #define MEMIF_ERR_UNDEFINED "undefined error"
@@ -423,6 +426,13 @@
     {
       memif_epfd = epoll_create (1);
       memif_control_fd_update_register (memif_control_fd_update);
+      if ((poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
+	{
+	  err = errno;
+	  DBG ("eventfd: %s", strerror (err));
+	  return memif_syscall_error_handler (err);
+	}
+      lm->control_fd_update (poll_cancel_fd, MEMIF_FD_EVENT_READ);
       DBG ("libmemif event polling initialized");
     }
 
@@ -925,6 +935,8 @@
   int en = 0, err = MEMIF_ERR_SUCCESS, i = 0;	/* 0 */
   uint16_t num;
   uint32_t events = 0;
+  uint64_t counter = 0;
+  ssize_t r = 0;
   memset (&evt, 0, sizeof (evt));
   evt.events = EPOLLIN | EPOLLOUT;
   sigset_t sigset;
@@ -932,11 +944,17 @@
   en = epoll_pwait (memif_epfd, &evt, 1, timeout, &sigset);
   if (en < 0)
     {
-      DBG ("epoll_pwait: %s", strerror (errno));
-      return -1;
+      err = errno;
+      DBG ("epoll_pwait: %s", strerror (err));
+      return memif_syscall_error_handler (err);
     }
   if (en > 0)
     {
+      if (evt.data.fd == poll_cancel_fd)
+	{
+	  r = read (evt.data.fd, &counter, sizeof (counter));
+	  return MEMIF_ERR_POLL_CANCEL;
+	}
       if (evt.events & EPOLLIN)
 	events |= MEMIF_FD_EVENT_READ;
       if (evt.events & EPOLLOUT)
@@ -949,6 +967,21 @@
   return 0;
 }
 
+int
+memif_cancel_poll_event ()
+{
+  uint64_t counter = 1;
+  ssize_t w = 0;
+
+  if (poll_cancel_fd == -1)
+    return 0;
+  w = write (poll_cancel_fd, &counter, sizeof (counter));
+  if (w < sizeof (counter))
+    return MEMIF_ERR_INT_WRITE;
+
+  return 0;
+}
+
 static void
 memif_msg_queue_free (memif_msg_queue_elt_t ** e)
 {
@@ -1536,7 +1569,7 @@
       *count_out += 1;
       mq->alloc_bufs -= chain_buf0;
     }
-  MEMIF_MEORY_BARRIER ();
+  MEMIF_MEMORY_BARRIER ();
   ring->tail = tail;
   DBG ("tail: %u", ring->tail);
 
@@ -1745,7 +1778,7 @@
       *tx += chain_buf0;
       curr_buf++;
     }
-  MEMIF_MEORY_BARRIER ();
+  MEMIF_MEMORY_BARRIER ();
   ring->head = head;
 
   mq->alloc_bufs -= *tx;
@@ -1941,40 +1974,36 @@
   l0 = 0;
 
   l1 = strlen ((char *) c->args.interface_name);
-  if (l0 + l1 <= buflen)
+  if (l0 + l1 < buflen)
     {
-      md->if_name = strncpy (buf + l0, (char *) c->args.interface_name, l1);
-      md->if_name[l0 + l1] = '\0';
+      md->if_name = strcpy (buf + l0, (char *) c->args.interface_name);
       l0 += l1 + 1;
     }
   else
     err = MEMIF_ERR_NOBUF_DET;
 
   l1 = strlen ((char *) c->args.instance_name);
-  if (l0 + l1 <= buflen)
+  if (l0 + l1 < buflen)
     {
-      md->inst_name = strncpy (buf + l0, (char *) c->args.instance_name, l1);
-      md->inst_name[l0 + l1] = '\0';
+      md->inst_name = strcpy (buf + l0, (char *) c->args.instance_name);
       l0 += l1 + 1;
     }
   else
     err = MEMIF_ERR_NOBUF_DET;
 
   l1 = strlen ((char *) c->remote_if_name);
-  if (l0 + l1 <= buflen)
+  if (l0 + l1 < buflen)
     {
-      md->remote_if_name = strncpy (buf + l0, (char *) c->remote_if_name, l1);
-      md->remote_if_name[l0 + l1] = '\0';
+      md->remote_if_name = strcpy (buf + l0, (char *) c->remote_if_name);
       l0 += l1 + 1;
     }
   else
     err = MEMIF_ERR_NOBUF_DET;
 
   l1 = strlen ((char *) c->remote_name);
-  if (l0 + l1 <= buflen)
+  if (l0 + l1 < buflen)
     {
-      md->remote_inst_name = strncpy (buf + l0, (char *) c->remote_name, l1);
-      md->remote_inst_name[l0 + l1] = '\0';
+      md->remote_inst_name = strcpy (buf + l0, (char *) c->remote_name);
       l0 += l1 + 1;
     }
   else
@@ -1985,22 +2014,23 @@
   if (c->args.secret)
     {
       l1 = strlen ((char *) c->args.secret);
-      md->secret = strncpy (buf + l0, (char *) c->args.secret, l1);
-      md->secret[l0 + l1] = '\0';
-      l0 += l1 + 1;
+      if (l0 + l1 < buflen)
+	{
+	  md->secret = strcpy (buf + l0, (char *) c->args.secret);
+	  l0 += l1 + 1;
+	}
+      else
+	err = MEMIF_ERR_NOBUF_DET;
     }
-  else
-    err = MEMIF_ERR_NOBUF_DET;
 
   md->role = (c->args.is_master) ? 0 : 1;
   md->mode = c->args.mode;
 
   l1 = strlen ((char *) c->args.socket_filename);
-  if (l0 + l1 <= buflen)
+  if (l0 + l1 < buflen)
     {
       md->socket_filename =
-	strncpy (buf + l0, (char *) c->args.socket_filename, l1);
-      md->socket_filename[l0 + l1] = '\0';
+	strcpy (buf + l0, (char *) c->args.socket_filename);
       l0 += l1 + 1;
     }
   else
@@ -2014,7 +2044,7 @@
   if (l0 + l1 <= buflen)
     {
       md->rx_queues = (memif_queue_details_t *) buf + l0;
-      l0 = l1 + 1;
+      l0 += l1;
     }
   else
     err = MEMIF_ERR_NOBUF_DET;
@@ -2034,7 +2064,7 @@
   if (l0 + l1 <= buflen)
     {
       md->tx_queues = (memif_queue_details_t *) buf + l0;
-      l0 = l1 + 1;
+      l0 += l1;
     }
   else
     err = MEMIF_ERR_NOBUF_DET;
@@ -2090,6 +2120,8 @@
   if (lm->pending_list)
     free (lm->pending_list);
   lm->pending_list = NULL;
+  if (poll_cancel_fd != -1)
+    close (poll_cancel_fd);
 
   return MEMIF_ERR_SUCCESS;	/* 0 */
 }