Hello community,

here is the log from the commit of package conmon for openSUSE:Factory checked 
in at 2020-03-25 23:44:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/conmon (Old)
 and      /work/SRC/openSUSE:Factory/.conmon.new.3160 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "conmon"

Wed Mar 25 23:44:47 2020 rev:11 rq:788098 version:2.0.14

Changes:
--------
--- /work/SRC/openSUSE:Factory/conmon/conmon.changes    2020-03-19 
19:49:09.056144337 +0100
+++ /work/SRC/openSUSE:Factory/.conmon.new.3160/conmon.changes  2020-03-25 
23:45:55.504045192 +0100
@@ -1,0 +2,9 @@
+Wed Mar 25 08:55:06 UTC 2020 - Sascha Grunert <[email protected]>
+
+- Update to v2.0.14
+  - drop usage of splice(2)
+  - avoid hanging on stdin
+  - stdio: sometimes quit main loop after io is done
+  - ignore sigpipe
+
+-------------------------------------------------------------------

Old:
----
  conmon-2.0.12.tar.xz

New:
----
  conmon-2.0.14.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ conmon.spec ++++++
--- /var/tmp/diff_new_pack.Cn9jgI/_old  2020-03-25 23:45:57.508045848 +0100
+++ /var/tmp/diff_new_pack.Cn9jgI/_new  2020-03-25 23:45:57.532045855 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           conmon
-Version:        2.0.12
+Version:        2.0.14
 Release:        0
 Summary:        An OCI container runtime monitor
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.Cn9jgI/_old  2020-03-25 23:45:57.608045880 +0100
+++ /var/tmp/diff_new_pack.Cn9jgI/_new  2020-03-25 23:45:57.608045880 +0100
@@ -2,8 +2,8 @@
 <service name="tar_scm" mode="disabled">
 <param name="url">https://github.com/containers/conmon</param>
 <param name="scm">git</param>
-<param name="versionformat">2.0.12</param>
-<param name="revision">v2.0.12</param>
+<param name="versionformat">2.0.14</param>
+<param name="revision">v2.0.14</param>
 </service>
 <service name="recompress" mode="disabled">
 <param name="file">conmon-*.tar</param>

++++++ conmon-2.0.12.tar.xz -> conmon-2.0.14.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/conmon-2.0.12/.dir-locals.el 
new/conmon-2.0.14/.dir-locals.el
--- old/conmon-2.0.12/.dir-locals.el    1970-01-01 01:00:00.000000000 +0100
+++ new/conmon-2.0.14/.dir-locals.el    2020-03-20 16:44:25.000000000 +0100
@@ -0,0 +1,3 @@
+((c-mode . ((fill-column . 109)
+            (c-basic-offset . 8)
+            (indent-tabs-mode t))))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/conmon-2.0.12/VERSION new/conmon-2.0.14/VERSION
--- old/conmon-2.0.12/VERSION   2020-03-16 17:55:00.000000000 +0100
+++ new/conmon-2.0.14/VERSION   2020-03-20 16:44:25.000000000 +0100
@@ -1 +1 @@
-2.0.12
+2.0.14
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/conmon-2.0.12/src/conmon.c 
new/conmon-2.0.14/src/conmon.c
--- old/conmon-2.0.12/src/conmon.c      2020-03-16 17:55:00.000000000 +0100
+++ new/conmon-2.0.14/src/conmon.c      2020-03-20 16:44:25.000000000 +0100
@@ -284,8 +284,12 @@
 /* Used for attach */
 struct conn_sock_s {
        int fd;
+       gboolean data_ready;
        gboolean readable;
        gboolean writable;
+       size_t remaining;
+       size_t off;
+       char buf[CONN_SOCK_BUF_SIZE];
 };
 GPtrArray *conn_socks = NULL;
 
@@ -489,12 +493,28 @@
                return G_SOURCE_REMOVE;
        }
 
+       /* End of input */
        if (read_eof || (has_hup && !has_input)) {
-               /* End of input */
-               if (pipe == STDOUT_PIPE)
+               /* There exists a case that the process has already exited
+                * and we know about it (because we checked our child processes)
+                * but we needed to run the main_loop to catch all the rest of 
the output
+                * (specifically, when we are exec, but not terminal)
+                * In this case, after both the stderr and stdout pipes have 
closed
+                * we should quit the loop. Otherwise, conmon will hang forever
+                * waiting for container_exit_cb that will never be called.
+                */
+               if (pipe == STDOUT_PIPE) {
                        masterfd_stdout = -1;
-               if (pipe == STDERR_PIPE)
+                       if (container_status >= 0 && masterfd_stderr < 0) {
+                               g_main_loop_quit(main_loop);
+                       }
+               }
+               if (pipe == STDERR_PIPE) {
                        masterfd_stderr = -1;
+                       if (container_status >= 0 && masterfd_stdout < 0) {
+                               g_main_loop_quit(main_loop);
+                       }
+               }
 
                close(fd);
                return G_SOURCE_REMOVE;
@@ -667,39 +687,8 @@
        return ret;
 }
 
-static gboolean conn_sock_cb(int fd, GIOCondition condition, gpointer 
user_data)
+static gboolean terminate_conn_sock(struct conn_sock_s *sock)
 {
-       struct conn_sock_s *sock = (struct conn_sock_s *)user_data;
-       ssize_t num_read = 0;
-
-       if ((condition & G_IO_IN) != 0) {
-               num_read = splice(fd, NULL, masterfd_stdin, NULL, 1 << 20, 0);
-               if (num_read > 0)
-                       return G_SOURCE_CONTINUE;
-
-               if (num_read < 0) {
-                       if (errno != ESPIPE && errno != EINVAL) {
-                               nwarn("Failed to write to container stdin");
-                       } else {
-                               /* Fallback to read-write.  This may lock if 
the consumer
-                                  doesn't read all the data.  */
-                               char buf[CONN_SOCK_BUF_SIZE];
-
-                               num_read = read(fd, buf, CONN_SOCK_BUF_SIZE);
-                               if (num_read < 0)
-                                       return G_SOURCE_CONTINUE;
-
-                               if (num_read > 0 && masterfd_stdin >= 0) {
-                                       if (write_all(masterfd_stdin, buf, 
num_read) < 0) {
-                                               nwarn("Failed to write to 
container stdin");
-                                       }
-                                       return G_SOURCE_CONTINUE;
-                               }
-                       }
-               }
-       }
-
-       /* End of input */
        conn_sock_shutdown(sock, SHUT_RD);
        if (masterfd_stdin >= 0 && opt_stdin) {
                if (!opt_leave_stdin_open) {
@@ -712,6 +701,90 @@
        return G_SOURCE_REMOVE;
 }
 
+static gboolean conn_sock_cb(G_GNUC_UNUSED int fd, GIOCondition condition, 
gpointer user_data);
+
+static void sock_try_write_to_masterfd_stdin(struct conn_sock_s *sock)
+{
+       if (!sock->remaining)
+               return;
+
+       ssize_t w = write(masterfd_stdin, sock->buf + sock->off, 
sock->remaining);
+       if (w < 0) {
+               nwarn("Failed to write to container stdin");
+       } else {
+               sock->off += w;
+               sock->remaining -= w;
+       }
+}
+
+static void write_to_masterfd_stdin(gpointer data, gpointer user_data)
+{
+       struct conn_sock_s *sock = (struct conn_sock_s *)data;
+       bool *has_data = user_data;
+
+       sock_try_write_to_masterfd_stdin(sock);
+
+       if (sock->remaining)
+               *has_data = true;
+       else if (sock->data_ready) {
+               sock->data_ready = false;
+               g_unix_fd_add(sock->fd, G_IO_IN | G_IO_HUP | G_IO_ERR, 
conn_sock_cb, sock);
+       }
+}
+
+static gboolean masterfd_write_cb(G_GNUC_UNUSED int fd, G_GNUC_UNUSED 
GIOCondition condition, G_GNUC_UNUSED gpointer user_data)
+{
+       bool has_data = FALSE;
+
+       if (masterfd_stdin < 0)
+               return G_SOURCE_REMOVE;
+
+       g_ptr_array_foreach(conn_socks, write_to_masterfd_stdin, &has_data);
+       if (has_data)
+               return G_SOURCE_CONTINUE;
+       return G_SOURCE_REMOVE;
+}
+
+static gboolean read_conn_sock(struct conn_sock_s *sock)
+{
+       ssize_t num_read;
+
+       /* There is still data in the buffer.  */
+       if (sock->remaining) {
+               sock->data_ready = true;
+               return G_SOURCE_REMOVE;
+       }
+
+       num_read = read(sock->fd, sock->buf, CONN_SOCK_BUF_SIZE);
+       if (num_read < 0)
+               return G_SOURCE_CONTINUE;
+
+       if (num_read == 0)
+               return terminate_conn_sock(sock);
+
+       /* num_read > 0 */
+       sock->remaining = num_read;
+       sock->off = 0;
+
+       sock_try_write_to_masterfd_stdin(sock);
+
+       /* Not everything was written to stdin, let's wait for the fd to be 
ready.  */
+       if (sock->remaining)
+               g_unix_fd_add(masterfd_stdin, G_IO_OUT, masterfd_write_cb, 
NULL);
+
+       return G_SOURCE_CONTINUE;
+}
+
+static gboolean conn_sock_cb(G_GNUC_UNUSED int fd, GIOCondition condition, 
gpointer user_data)
+{
+       struct conn_sock_s *sock = (struct conn_sock_s *)user_data;
+
+       if (condition & G_IO_IN)
+               return read_conn_sock(sock);
+
+       return terminate_conn_sock(sock);
+}
+
 static gboolean attach_cb(int fd, G_GNUC_UNUSED GIOCondition condition, 
G_GNUC_UNUSED gpointer user_data)
 {
        int conn_fd = accept(fd, NULL, NULL);
@@ -730,6 +803,9 @@
                conn_sock->fd = conn_fd;
                conn_sock->readable = true;
                conn_sock->writable = true;
+               conn_sock->off = 0;
+               conn_sock->remaining = 0;
+               conn_sock->data_ready = false;
                g_unix_fd_add(conn_sock->fd, G_IO_IN | G_IO_HUP | G_IO_ERR, 
conn_sock_cb, conn_sock);
                g_ptr_array_add(conn_socks, conn_sock);
                ninfof("Accepted connection %d", conn_sock->fd);
@@ -1329,6 +1405,8 @@
                close(oom_score_fd);
        }
 
+       /* ignoring SIGPIPE prevents conmon from being spuriously killed */
+       signal(SIGPIPE, SIG_IGN);
 
        main_loop = g_main_loop_new(NULL, FALSE);
 
@@ -1460,6 +1538,9 @@
 
                        masterfd_stdin = fds[1];
                        slavefd_stdin = fds[0];
+
+                       if (g_unix_set_fd_nonblocking(masterfd_stdin, TRUE, 
NULL) == FALSE)
+                               nwarn("Failed to set masterfd_stdin to non 
blocking");
                }
 
                if (pipe2(fds, O_CLOEXEC) < 0)
@@ -1772,6 +1853,9 @@
               specifically, the check child processes call above could set the 
container
               status if it is a quickly exiting command. We only want to run 
the loop if
               this hasn't happened yet.
+               Note: there exists a chance that we have the container_status, 
are exec, and api>=1,
+               but are not terminal. In this case, we still want to run to 
process all of the output,
+               but will need to exit once all the i/o is read. This will be 
handled in stdio_cb above.
        */
        if (opt_api_version < 1 || !opt_exec || !opt_terminal || 
container_status < 0)
                g_main_loop_run(main_loop);


Reply via email to