S390: Move utf8-utf32-z9.c to multiarch folder and use s390_libc_ifunc_expr macro.
[glibc.git] / posix / tst-spawn3.c
blob8577b03d011aea5c5fc02134158ea3f9db39df1c
1 /* Check posix_spawn add file actions.
2 Copyright (C) 2016-2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <stdio.h>
20 #include <spawn.h>
21 #include <error.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/wait.h>
27 #include <sys/resource.h>
29 static int do_test (void);
30 #define TEST_FUNCTION do_test ()
31 #include <test-skeleton.c>
33 static int
34 do_test (void)
36 /* The test checks if posix_spawn open file action close the file descriptor
37 before opening a new one in case the input file descriptor is already
38 opened. It does by exhausting all file descriptors on the process before
39 issue posix_spawn. It then issues a posix_spawn for '/bin/sh echo $$'
40 and add two rules:
42 1. Redirect stdout to a temporary filepath
43 2. Redirect stderr to stdout
45 If the implementation does not close the file 1. will fail with
46 EMFILE. */
48 struct rlimit rl;
49 int max_fd = 24;
51 /* Set maximum number of file descriptor to a low value to avoid open
52 too many files in environments where RLIMIT_NOFILE is large and to
53 limit the array size to track the opened file descriptors. */
55 if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
57 printf ("error: getrlimit RLIMIT_NOFILE failed");
58 exit (EXIT_FAILURE);
61 max_fd = (rl.rlim_cur < max_fd ? rl.rlim_cur : max_fd);
62 rl.rlim_cur = max_fd;
64 if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
66 printf ("error: setrlimit RLIMIT_NOFILE to %u failed", max_fd);
67 exit (EXIT_FAILURE);
70 /* Exhauste the file descriptor limit with temporary files. */
71 int files[max_fd];
72 int nfiles = 0;
73 for (;;)
75 int fd = create_temp_file ("tst-spawn3.", NULL);
76 if (fd == -1)
78 if (errno != EMFILE)
80 printf ("error: create_temp_file returned -1 with "
81 "errno != EMFILE\n");
82 exit (EXIT_FAILURE);
84 break;
86 files[nfiles++] = fd;
89 posix_spawn_file_actions_t a;
90 if (posix_spawn_file_actions_init (&a) != 0)
92 puts ("error: spawn_file_actions_init failed");
93 exit (EXIT_FAILURE);
96 /* Executes a /bin/sh echo $$ 2>&1 > /tmp/tst-spawn3.pid . */
97 const char pidfile[] = "/tmp/tst-spawn3.pid";
98 if (posix_spawn_file_actions_addopen (&a, STDOUT_FILENO, pidfile, O_WRONLY |
99 O_CREAT | O_TRUNC, 0644) != 0)
101 puts ("error: spawn_file_actions_addopen failed");
102 exit (EXIT_FAILURE);
105 if (posix_spawn_file_actions_adddup2 (&a, STDOUT_FILENO, STDERR_FILENO) != 0)
107 puts ("error: spawn_file_actions_addclose");
108 exit (EXIT_FAILURE);
111 /* Since execve (called by posix_spawn) might require to open files to
112 actually execute the shell script, setup to close the temporary file
113 descriptors. */
114 for (int i=0; i<nfiles; i++)
116 if (posix_spawn_file_actions_addclose (&a, files[i]))
118 printf ("error: posix_spawn_file_actions_addclose failed");
119 exit (EXIT_FAILURE);
123 char *spawn_argv[] = { (char *) _PATH_BSHELL, (char *) "-c",
124 (char *) "echo $$", NULL };
125 pid_t pid;
126 if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, spawn_argv, NULL) != 0)
128 puts ("error: posix_spawn failed");
129 exit (EXIT_FAILURE);
132 int status;
133 int err = waitpid (pid, &status, 0);
134 if (err != pid)
136 puts ("error: waitpid failed");
137 exit (EXIT_FAILURE);
140 /* Close the temporary files descriptor so it can check posix_spawn
141 output. */
142 for (int i=0; i<nfiles; i++)
144 if (close (files[i]))
146 printf ("error: close failed\n");
147 exit (EXIT_FAILURE);
151 int pidfd = open (pidfile, O_RDONLY);
152 if (pidfd == -1)
154 printf ("error: open pidfile failed\n");
155 exit (EXIT_FAILURE);
158 char buf[64];
159 ssize_t n;
160 if ((n = read (pidfd, buf, sizeof (buf))) < 0)
162 printf ("error: read pidfile failed\n");
163 exit (EXIT_FAILURE);
166 unlink (pidfile);
168 /* We only expect to read the PID. */
169 char *endp;
170 long int rpid = strtol (buf, &endp, 10);
171 if (*endp != '\n')
173 printf ("error: didn't parse whole line: \"%s\"\n", buf);
174 exit (EXIT_FAILURE);
176 if (endp == buf)
178 puts ("error: read empty line");
179 exit (EXIT_FAILURE);
182 if (rpid != pid)
184 printf ("error: found \"%s\", expected PID %ld\n", buf, (long int) pid);
185 exit (EXIT_FAILURE);
188 return 0;