[Libguestfs] [PATCH libnbd] api: New nbd_kill_command API for sending a signal to the command subprocess.

Richard W.M. Jones
Thu, 25 Jul 2019 19:15:00 -0000

Reverts commit 387cbe67c3db27e8a61117fedb6e7fad76e409ef.
---
 generator/generator       | 18 +++++++++++++++++-
 lib/handle.c              | 28 +++++++++++++++++++++++++++-
 tests/closure-lifetimes.c |  4 +++-
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/generator/generator b/generator/generator
index 2cd83f1..25e4aa5 100755
--- a/generator/generator
+++ b/generator/generator
@@ -1191,7 +1191,9 @@ has been made.";
     longdesc = "\
 Run the command as a subprocess and connect to it over
 stdin/stdout.  This is for use with NBD servers which can
-behave like inetd clients, such as C<nbdkit --single>.";
+behave like inetd clients, such as C<nbdkit --single>.
+
+See also C<nbd_kill_command>.";
   };

   "read_only", {
@@ -2244,6 +2246,20 @@ The release number is incremented for each release along
a particular
 branch.";
   };

+  "kill_command", {
+    default_call with
+    args = [ Int "signal" ]; ret = RErr;
+    shortdesc = "kill server running as a subprocess";
+    longdesc = "\
+This call may be used to kill the server running as a subprocess
+that was previously created using C<nbd_connect_command>.  You
+do not need to use this call.  It is only needed if the server
+does not exit when the socket is closed.
+
+The C<signal> flag is the optional signal number to send
+(see L<signal(7)>).  If signal is C<0> then C<SIGTERM> is
sent.";
+  };
+
   "supports_tls", {
     default_call with
     args = []; ret = RBool; is_locked = false; may_set_error = false;
diff --git a/lib/handle.c b/lib/handle.c
index 1fe4467..ccfea42 100644
--- a/lib/handle.c
+++ b/lib/handle.c
@@ -22,6 +22,8 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
+#include <signal.h>
+#include <assert.h>
 #include <netdb.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -124,7 +126,7 @@ nbd_close (struct nbd_handle *h)
     freeaddrinfo (h->result);
   if (h->sock)
     h->sock->ops->close (h->sock);
-  if (h->pid >= 0) /* XXX kill it? */
+  if (h->pid > 0)
     waitpid (h->pid, NULL, 0);

   free (h->export_name);
@@ -215,6 +217,30 @@ nbd_unlocked_get_version (struct nbd_handle *h)
   return PACKAGE_VERSION;
 }

+int
+nbd_unlocked_kill_command (struct nbd_handle *h, int signal)
+{
+  if (h->pid == -1) {
+    set_error (ESRCH, "no subprocess exists");
+    return -1;
+  }
+  assert (h->pid > 0);
+
+  if (signal == 0)
+    signal = SIGTERM;
+  if (signal < 0) {
+    set_error (EINVAL, "invalid signal number: %d", signal);
+    return -1;
+  }
+
+  if (kill (h->pid, signal) == -1) {
+    set_error (errno, "kill");
+    return -1;
+  }
+
+  return 0;
+}
+
 /* NB: is_locked = false, may_set_error = false. */
 int
 nbd_unlocked_supports_tls (struct nbd_handle *h)
diff --git a/tests/closure-lifetimes.c b/tests/closure-lifetimes.c
index 910bdf4..3ddf4c1 100644
--- a/tests/closure-lifetimes.c
+++ b/tests/closure-lifetimes.c
@@ -35,7 +35,7 @@ static char *nbdkit_delay[]    { "nbdkit",
"-s", "--exit-with-parent", "-v",
     "--filter=delay",
     "null", "size=512",
-    "delay-read=3",
+    "delay-read=10",
     NULL };

 static unsigned debug_fn_valid;
@@ -134,6 +134,7 @@ main (int argc, char *argv[])
   assert (read_cb_free == 1);
   assert (completion_cb_free == 1);

+  nbd_kill_command (nbd, 0);
   nbd_close (nbd);

   /* Test command callbacks are freed if the handle is closed without
@@ -149,6 +150,7 @@ main (int argc, char *argv[])
                                               read_cb, NULL,
                                               completion_cb, NULL, 0);
   if (cookie == -1) NBD_ERROR;
+  nbd_kill_command (nbd, 0);
   nbd_close (nbd);

   assert (read_cb_free == 1);
--
2.22.0