tests: vsock: Use VMADDR_CID_LOCAL for loopback testing.
[nbdkit/ericb.git] / tests / test-exit-with-parent.c
blob9c98db44534e2ba395668d4fe9be22aed7120bf6
1 /* nbdkit
2 * Copyright (C) 2017 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/wait.h>
43 #include <errno.h>
45 #include "exit-with-parent.h"
46 #include "test.h"
48 static char pidpath[] = "/tmp/nbdkitpidXXXXXX";
50 static void run_test (void);
52 int
53 main (int argc, char *argv[])
55 #ifndef HAVE_EXIT_WITH_PARENT
56 printf ("--exit-with-parent is not implemented on this platform, skipping\n");
57 exit (77);
58 #else
59 run_test ();
60 exit (EXIT_SUCCESS);
61 #endif
64 static void
65 run_test (void)
67 pid_t cpid, nbdpid;
68 int i, fd, status;
69 FILE *fp;
70 ssize_t r;
71 size_t n;
72 char *pidstr;
74 fd = mkstemp (pidpath);
75 if (fd == -1) {
76 perror ("mkstemp");
77 exit (EXIT_FAILURE);
79 close (fd);
80 unlink (pidpath);
82 /* We're going to create:
84 * monitoring process (this)
85 * |
86 * `--- child process waits for nbdkit to start then exits (cpid)
87 * |
88 * `--- exec nbdkit --exit-with-parent (pidpath)
90 * We can read the nbdkit PID in the monitoring process using
91 * the pidpath file.
93 cpid = fork ();
94 if (cpid == 0) { /* child process */
95 nbdpid = fork ();
96 if (nbdpid == 0) { /* exec nbdkit process */
97 const char *argv[] = {
98 "nbdkit", "-U", "-", "-P", pidpath, "-f", "--exit-with-parent",
99 "example1",
100 NULL
103 execvp ("nbdkit", (char **) argv);
104 perror ("exec: nbdkit");
105 _exit (EXIT_FAILURE);
108 /* Wait for the pidfile to turn up, which indicates that nbdkit has
109 * started up successfully and is ready to serve requests. However
110 * if 'nbdpid' exits in this time it indicates a failure to start up.
111 * Also there is a timeout in case nbdkit hangs.
113 for (i = 0; i < NBDKIT_START_TIMEOUT; ++i) {
114 if (waitpid (nbdpid, NULL, WNOHANG) == nbdpid)
115 goto early_exit;
117 if (kill (nbdpid, 0) == -1) {
118 if (errno == ESRCH) {
119 early_exit:
120 fprintf (stderr,
121 "%s FAILED: nbdkit exited before starting to serve files\n",
122 program_name);
123 nbdpid = 0;
124 exit (EXIT_FAILURE);
126 perror ("kill");
129 if (access (pidpath, F_OK) == 0)
130 break;
132 sleep (1);
135 /* nbdkit is now running, check that --exit-with-parent works
136 * by exiting abruptly here.
138 _exit (EXIT_SUCCESS);
141 /* Monitoring process. */
142 if (waitpid (cpid, &status, 0) == -1) {
143 perror ("waitpid (cpid)");
144 exit (EXIT_FAILURE);
146 if (WIFEXITED (status) && WEXITSTATUS (status) != 1)
147 exit (WEXITSTATUS (status));
148 if (WIFSIGNALED (status)) {
149 fprintf (stderr, "child terminated by signal %d\n", WTERMSIG (status));
150 exit (EXIT_FAILURE);
152 if (WIFSTOPPED (status)) {
153 fprintf (stderr, "child stopped by signal %d\n", WSTOPSIG (status));
154 exit (EXIT_FAILURE);
157 /* Get the PID of nbdkit from the pidpath file. */
158 fp = fopen (pidpath, "r");
159 if (fp == NULL) {
160 perror (pidpath);
161 exit (EXIT_FAILURE);
163 r = getline (&pidstr, &n, fp);
164 if (r == -1) {
165 perror ("read");
166 exit (EXIT_FAILURE);
168 if (sscanf (pidstr, "%d", &nbdpid) != 1) {
169 fprintf (stderr, "could not read nbdkit PID from -P pidfile (%s)\n",
170 pidpath);
171 exit (EXIT_FAILURE);
173 fclose (fp);
174 free (pidstr);
175 unlink (pidpath);
177 /* We expect PID to go away, but it might take a few seconds. */
178 for (i = 0; i < NBDKIT_START_TIMEOUT; ++i) {
179 if (kill (nbdpid, 0) == -1) {
180 if (errno == ESRCH) goto done; /* good - gone away */
181 perror ("kill");
182 exit (EXIT_FAILURE);
185 sleep (1);
188 fprintf (stderr, "--exit-with-parent does not appear to work\n");
189 exit (EXIT_FAILURE);
191 done: