On 7/25/19 3:19 PM, Eric Blake wrote:
On 7/25/19 2:15 PM, Richard W.M. Jones wrote:
Reverts commit 387cbe67c3db27e8a61117fedb6e7fad76e409ef. --- generator/generator | 18 +++++++++++++++++- lib/handle.c | 28 +++++++++++++++++++++++++++- tests/closure-lifetimes.c | 4 +++- 3 files changed, 47 insertions(+), 3 deletions(-)
tests/server-death.c can be simplified (no longer has to use --pidfile to learn where to send its kill); could be done on top.
Done now: From a9c42e136ef52361a13a7a2f2e7eae6cadb36421 Mon Sep 17 00:00:00 2001 From: Eric Blake <eblake@redhat.com> Date: Thu, 25 Jul 2019 19:58:32 -0500 Subject: [libnbd PATCH] tests: Simplify server-death with nbd_kill_command Now that libnbd can forward our kill request, we don't need to manage a pidfile ourselves. And we don't even have to ignore SIGCHLD to avoid waiting for a zombie; all we really need is our existing nbd_aio_poll loop to detect that the connection dies. --- tests/server-death.c | 100 ++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 69 deletions(-) diff --git a/tests/server-death.c b/tests/server-death.c index cd58190..56e7e51 100644 --- a/tests/server-death.c +++ b/tests/server-death.c @@ -25,7 +25,6 @@ #include <stdlib.h> #include <string.h> #include <errno.h> -#include <unistd.h> #include <signal.h> #include <libnbd.h> @@ -56,69 +55,46 @@ main (int argc, char *argv[]) const char *msg; char buf[512]; int64_t cookie; - char pidfile[] = "/tmp/libnbd-test-disconnectXXXXXX"; - int fd; - pid_t pid; int r; - int delay = 0; - const char *cmd[] = { "nbdkit", "--pidfile", pidfile, "-s", - "--exit-with-parent", "--filter=delay", "memory", - "size=1m", "delay-read=15", "delay-trim=15", NULL }; + const char *cmd[] = { "nbdkit", "-s", "--exit-with-parent", + "--filter=delay", "memory", "size=1m", + "delay-read=15", "delay-trim=15", NULL }; progname = argv[0]; - /* We're going to kill the child, but don't want to wait for a zombie */ - if (signal (SIGCHLD, SIG_IGN) == SIG_ERR) { - fprintf (stderr, "%s: signal: %s\n", argv[0], strerror (errno)); - exit (EXIT_FAILURE); - } - - fd = mkstemp (pidfile); - if (fd < 0) { - fprintf (stderr, "%s: mkstemp: %s\n", argv[0], strerror (errno)); - exit (EXIT_FAILURE); - } - nbd = nbd_create (); if (nbd == NULL) { fprintf (stderr, "%s: %s\n", argv[0], nbd_get_error ()); - goto fail; + exit (EXIT_FAILURE); } /* Connect to a slow server. */ if (nbd_connect_command (nbd, (char **) cmd) == -1) { fprintf (stderr, "%s: %s\n", argv[0], nbd_get_error ()); - goto fail; - } - if (read (fd, buf, sizeof buf) == -1) { - fprintf (stderr, "%s: read: %s\n", argv[0], strerror (errno)); - goto fail; - } - pid = atoi (buf); - if (pid <= 0) { - fprintf (stderr, "%s: unable to parse server's pid\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } /* Issue a read and trim that should not complete yet. Set up the * trim to auto-retire via callback. */ if ((cookie = nbd_aio_pread (nbd, buf, sizeof buf, 0, 0)) == -1) { - fprintf (stderr, "%s: test failed: nbd_aio_pread\n", argv[0]); - goto fail; + fprintf (stderr, "%s: test failed: nbd_aio_pread: %s\n", argv[0], + nbd_get_error ()); + exit (EXIT_FAILURE); } if (nbd_aio_trim_callback (nbd, sizeof buf, 0, callback, NULL, 0) == -1) { - fprintf (stderr, "%s: test failed: nbd_aio_trim_callback\n", argv[0]); - goto fail; + fprintf (stderr, "%s: test failed: nbd_aio_trim_callback: %s\n", argv[0], + nbd_get_error ()); + exit (EXIT_FAILURE); } if (nbd_aio_peek_command_completed (nbd) != 0) { fprintf (stderr, "%s: test failed: nbd_aio_peek_command_completed\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } if (nbd_aio_command_completed (nbd, cookie) != 0) { fprintf (stderr, "%s: test failed: nbd_aio_command_completed\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } /* Kill the server forcefully (SIGINT is not always strong enough, @@ -126,47 +102,39 @@ main (int argc, char *argv[]) * actually exiting), although it's a race whether our signal * arrives while nbdkit has a pending transaction. */ - if (kill (pid, SIGKILL) == -1) { - fprintf (stderr, "%s: kill: %s\n", argv[0], strerror (errno)); - goto fail; - } - /* Wait up to 10 seconds, 100 ms at a time */ - while (kill (pid, 0) == 0) { - if (delay++ > 100) { - fprintf (stderr, "%s: kill taking too long\n", argv[0]); - goto fail; - } - usleep (100 * 1000); + if (nbd_kill_command (nbd, SIGKILL) == -1) { + fprintf (stderr, "%s: test failed: nbd_kill_command: %s\n", argv[0], + nbd_get_error ()); + exit (EXIT_FAILURE); } - /* This part is somewhat racy if we don't wait for the process death - * above - depending on load and timing, nbd_poll may succeed or - * fail, and we may transition to either CLOSED (the state machine - * saw a clean EOF) or DEAD (the state machine saw a stranded - * transaction or POLLERR). + /* This part is somewhat racy depending on how fast we run before + * the server process exits - depending on load and timing, nbd_poll + * may succeed or fail, and we may transition to either CLOSED (the + * state machine saw a clean EOF) or DEAD (the state machine saw a + * stranded transaction or POLLERR). */ while ((r = nbd_poll (nbd, 1000)) == 1) if (nbd_aio_is_dead (nbd) || nbd_aio_is_closed (nbd)) break; if (!(nbd_aio_is_dead (nbd) || nbd_aio_is_closed (nbd))) { fprintf (stderr, "%s: test failed: server death not detected\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } /* Detection of the dead server completes all remaining in-flight commands */ if (nbd_aio_in_flight (nbd) != 0) { - fprintf (stderr, "%s: test failed: nbd_aio_in_flight\n", - argv[0]); - goto fail; + fprintf (stderr, "%s: test failed: nbd_aio_in_flight\n", argv[0]); + exit (EXIT_FAILURE); } if (nbd_aio_peek_command_completed (nbd) != cookie) { fprintf (stderr, "%s: test failed: nbd_aio_peek_command_completed\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } if (nbd_aio_command_completed (nbd, cookie) != -1) { fprintf (stderr, "%s: test failed: nbd_aio_command_completed\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } msg = nbd_get_error (); err = nbd_get_errno (); @@ -175,19 +143,19 @@ main (int argc, char *argv[]) if (err != ENOTCONN) { fprintf (stderr, "%s: test failed: unexpected errno %d (%s)\n", argv[0], err, strerror (err)); - goto fail; + exit (EXIT_FAILURE); } /* With all commands retired, no further command should be pending */ if (!trim_retired) { fprintf (stderr, "%s: test failed: nbd_aio_trim_callback not retired\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } if (nbd_aio_peek_command_completed (nbd) != -1) { fprintf (stderr, "%s: test failed: nbd_aio_peek_command_completed\n", argv[0]); - goto fail; + exit (EXIT_FAILURE); } msg = nbd_get_error (); err = nbd_get_errno (); @@ -196,15 +164,9 @@ main (int argc, char *argv[]) if (err != EINVAL) { fprintf (stderr, "%s: test failed: unexpected errno %d (%s)\n", argv[0], err, strerror (err)); - goto fail; + exit (EXIT_FAILURE); } - close (fd); - unlink (pidfile); nbd_close (nbd); exit (EXIT_SUCCESS); - - fail: - unlink (pidfile); - exit (EXIT_FAILURE); } -- 2.20.1 -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org