Update Red Hat Copyright Notices
[nbdkit.git] / tests / test-exit-with-parent.c
blob3f6cc3f4d64922428e27eef470f6478613375b28
1 /* nbdkit
2 * Copyright Red Hat
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 <signal.h>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <sys/types.h>
45 #ifdef HAVE_SYS_WAIT_H
46 #include <sys/wait.h>
47 #endif
49 #include "test.h"
51 static char pidpath[] = "/tmp/nbdkitpidXXXXXX";
53 static void run_test (void);
55 int
56 main (int argc, char *argv[])
58 if (system ("nbdkit --exit-with-parent --version") != 0) {
59 printf ("%s: --exit-with-parent is not implemented on this platform, "
60 "skipping\n",
61 argv[0]);
62 exit (77);
65 run_test ();
66 exit (EXIT_SUCCESS);
69 static void
70 run_test (void)
72 pid_t ppid, nbdpid;
73 int i, fd, status;
74 FILE *fp;
75 ssize_t r;
76 size_t n;
77 char *pidstr = NULL;
79 fd = mkstemp (pidpath);
80 if (fd == -1) {
81 perror ("mkstemp");
82 exit (EXIT_FAILURE);
84 close (fd);
85 unlink (pidpath);
87 /* We're going to create:
89 * monitoring process (this)
90 * |
91 * `--- parent of nbdkit: waits for nbdkit to start then exits (ppid)
92 * |
93 * `--- exec nbdkit --exit-with-parent (pidpath)
95 * We can read the nbdkit PID in the monitoring process using
96 * the pidpath file.
98 ppid = fork ();
99 if (ppid == 0) { /* parent of nbdkit */
100 nbdpid = fork ();
101 if (nbdpid == 0) { /* exec nbdkit process */
102 const char *argv[] = {
103 "nbdkit", "-U", "-", "-P", pidpath, "-fv", "--exit-with-parent",
104 "example1",
105 NULL
108 execvp ("nbdkit", (char **) argv);
109 perror ("exec: nbdkit");
110 _exit (EXIT_FAILURE);
113 printf ("parent of nbdkit: "
114 "monitoring process (test) = %d, "
115 "parent of nbdkit = %d, "
116 "nbdkit = %d\n",
117 (int) getppid (), (int) getpid (), nbdpid);
118 fflush (stdout);
120 /* Wait for the pidfile to turn up, which indicates that nbdkit has
121 * started up successfully and is ready to serve requests. However
122 * if 'nbdpid' exits in this time it indicates a failure to start up.
123 * Also there is a timeout in case nbdkit hangs.
125 for (i = 0; i < NBDKIT_START_TIMEOUT; ++i) {
126 if (waitpid (nbdpid, NULL, WNOHANG) == nbdpid)
127 goto early_exit;
129 if (kill (nbdpid, 0) == -1) {
130 if (errno == ESRCH) {
131 early_exit:
132 fprintf (stderr,
133 "%s FAILED: nbdkit exited before starting to serve files\n",
134 program_name);
135 nbdpid = 0;
136 exit (EXIT_FAILURE);
138 perror ("kill");
141 if (access (pidpath, F_OK) == 0)
142 break;
144 sleep (1);
147 printf ("parent of nbdkit: exiting\n");
148 fflush (stdout);
150 /* nbdkit is now running, check that --exit-with-parent works
151 * by exiting abruptly here.
153 _exit (EXIT_SUCCESS);
156 /* Monitoring process. */
157 printf ("monitor: waiting for parent of nbdkit to finish and exit\n");
158 fflush (stdout);
160 if (waitpid (ppid, &status, 0) == -1) {
161 perror ("waitpid (ppid)");
162 exit (EXIT_FAILURE);
164 if (WIFEXITED (status) && WEXITSTATUS (status) != 0) {
165 fprintf (stderr, "child exited unexpectedly with non-zero exit code %d\n",
166 WEXITSTATUS (status));
167 exit (WEXITSTATUS (status));
169 if (WIFSIGNALED (status)) {
170 fprintf (stderr, "child terminated by signal %d\n", WTERMSIG (status));
171 exit (EXIT_FAILURE);
173 if (WIFSTOPPED (status)) {
174 fprintf (stderr, "child stopped by signal %d\n", WSTOPSIG (status));
175 exit (EXIT_FAILURE);
178 /* Get the PID of nbdkit from the pidpath file. */
179 fp = fopen (pidpath, "r");
180 if (fp == NULL) {
181 perror (pidpath);
182 exit (EXIT_FAILURE);
184 r = getline (&pidstr, &n, fp);
185 if (r == -1) {
186 perror ("read");
187 exit (EXIT_FAILURE);
189 if (sscanf (pidstr, "%d", &nbdpid) != 1) {
190 fprintf (stderr, "could not read nbdkit PID from -P pidfile (%s)\n",
191 pidpath);
192 exit (EXIT_FAILURE);
194 fclose (fp);
195 free (pidstr);
196 unlink (pidpath);
198 printf ("monitor: found PID of nbdkit = %d\n", nbdpid);
199 fflush (stdout);
201 /* We expect PID to go away, but it might take a few seconds. */
202 for (i = 0; i < NBDKIT_START_TIMEOUT; ++i) {
203 if (kill (nbdpid, 0) == -1) {
204 if (errno == ESRCH) goto done; /* good - gone away */
205 perror ("kill");
206 exit (EXIT_FAILURE);
209 sleep (1);
212 fprintf (stderr, "--exit-with-parent does not appear to work\n");
213 exit (EXIT_FAILURE);
215 done:
216 printf ("monitor: success: nbdkit exited with parent\n");
217 fflush (stdout);