Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #ifndef _PROCESS_H_
6 : : #define _PROCESS_H_
7 : :
8 : : #include <errno.h> /* errno */
9 : : #include <limits.h> /* PATH_MAX */
10 : : #ifndef RTE_EXEC_ENV_WINDOWS
11 : : #include <libgen.h> /* basename et al */
12 : : #include <sys/wait.h>
13 : : #endif
14 : : #include <stdlib.h> /* NULL */
15 : : #include <string.h> /* strerror */
16 : : #include <unistd.h> /* readlink */
17 : : #include <dirent.h>
18 : :
19 : : #include <rte_string_fns.h> /* strlcpy */
20 : : #include <rte_devargs.h>
21 : : #include <rte_eal.h>
22 : :
23 : : #ifdef RTE_EXEC_ENV_FREEBSD
24 : : #define self "curproc"
25 : : #define exe "file"
26 : : #else
27 : : #define self "self"
28 : : #define exe "exe"
29 : : #endif
30 : :
31 : : #ifdef RTE_LIB_PDUMP
32 : : #ifdef RTE_NET_RING
33 : : #include <rte_thread.h>
34 : : extern uint32_t send_pkts(void *empty);
35 : : extern uint16_t flag_for_send_pkts;
36 : : #endif
37 : : #endif
38 : :
39 : : #define PREFIX_ALLOW "--allow="
40 : : #define PREFIX_DRIVER_PATH "--driver-path="
41 : :
42 : : static int
43 : 0 : add_parameter_allow(char **argv, int max_capacity)
44 : : {
45 : : struct rte_devargs *devargs;
46 : : int count = 0;
47 : :
48 [ # # ]: 0 : RTE_EAL_DEVARGS_FOREACH(NULL, devargs) {
49 [ # # ]: 0 : if (strlen(devargs->name) == 0)
50 : 0 : continue;
51 : :
52 [ # # # # ]: 0 : if (devargs->data == NULL || strlen(devargs->data) == 0) {
53 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_ALLOW"%s", devargs->name) < 0)
54 : : break;
55 : : } else {
56 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_ALLOW"%s,%s",
57 : 0 : devargs->name, devargs->data) < 0)
58 : : break;
59 : : }
60 : :
61 [ # # ]: 0 : if (++count == max_capacity)
62 : : break;
63 : : }
64 : :
65 : 0 : return count;
66 : : }
67 : :
68 : : static int
69 : 0 : add_parameter_driver_path(char **argv, int max_capacity)
70 : : {
71 : : const char *driver_path;
72 : : int count = 0;
73 : :
74 [ # # ]: 0 : RTE_EAL_DRIVER_PATH_FOREACH(driver_path, true) {
75 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_DRIVER_PATH"%s", driver_path) < 0)
76 : : break;
77 : :
78 [ # # ]: 0 : if (++count == max_capacity)
79 : : break;
80 : : }
81 : :
82 : 0 : return count;
83 : : }
84 : :
85 : : /*
86 : : * launches a second copy of the test process using the given argv parameters,
87 : : * which should include argv[0] as the process name. To identify in the
88 : : * subprocess the source of the call, the env_value parameter is set in the
89 : : * environment as $RTE_TEST
90 : : */
91 : : static inline int
92 : 132 : process_dup(const char *const argv[], int numargs, const char *env_value)
93 : : {
94 : : int num = 0;
95 : : char **argv_cpy;
96 : : int allow_num;
97 : : int driver_path_num;
98 : : int argv_num;
99 : : int i, status;
100 : : char path[32];
101 : : #ifdef RTE_LIB_PDUMP
102 : : #ifdef RTE_NET_RING
103 : : rte_thread_t thread;
104 : : int rc;
105 : : #endif
106 : : #endif
107 : :
108 : 132 : pid_t pid = fork();
109 [ + - ]: 132 : if (pid < 0)
110 : : return -1;
111 [ - + ]: 132 : else if (pid == 0) {
112 : 0 : allow_num = rte_devargs_type_count(RTE_DEVTYPE_ALLOWED);
113 : 0 : driver_path_num = rte_eal_driver_path_count(true);
114 : 0 : argv_num = numargs + allow_num + driver_path_num + 1;
115 : 0 : argv_cpy = calloc(argv_num, sizeof(char *));
116 [ # # ]: 0 : if (!argv_cpy)
117 : 0 : rte_panic("Memory allocation failed\n");
118 : :
119 : : /* make a copy of the arguments to be passed to exec */
120 [ # # ]: 0 : for (i = 0; i < numargs; i++) {
121 : 0 : argv_cpy[i] = strdup(argv[i]);
122 [ # # ]: 0 : if (argv_cpy[i] == NULL)
123 : 0 : rte_panic("Error dup args\n");
124 : : }
125 [ # # ]: 0 : if (allow_num > 0)
126 : 0 : num = add_parameter_allow(&argv_cpy[i], allow_num);
127 : 0 : num += numargs;
128 : :
129 [ # # ]: 0 : if (driver_path_num > 0) {
130 : 0 : int added = add_parameter_driver_path(&argv_cpy[num], driver_path_num);
131 : 0 : num += added;
132 : : }
133 : :
134 : : #ifdef RTE_EXEC_ENV_LINUX
135 : : {
136 : : const char *procdir = "/proc/" self "/fd/";
137 : : struct dirent *dirent;
138 : : char *endptr;
139 : : int fd, fdir;
140 : : DIR *dir;
141 : :
142 : : /* close all open file descriptors, check /proc/self/fd
143 : : * to only call close on open fds. Exclude fds 0, 1 and
144 : : * 2
145 : : */
146 : 0 : dir = opendir(procdir);
147 [ # # ]: 0 : if (dir == NULL) {
148 : 0 : rte_panic("Error opening %s: %s\n", procdir,
149 : : strerror(errno));
150 : : }
151 : :
152 : 0 : fdir = dirfd(dir);
153 [ # # ]: 0 : if (fdir < 0) {
154 : 0 : status = errno;
155 : 0 : closedir(dir);
156 : 0 : rte_panic("Error %d obtaining fd for dir %s: %s\n",
157 : : fdir, procdir,
158 : : strerror(status));
159 : : }
160 : :
161 [ # # ]: 0 : while ((dirent = readdir(dir)) != NULL) {
162 : :
163 [ # # ]: 0 : if (strcmp(dirent->d_name, ".") == 0 ||
164 [ # # ]: 0 : strcmp(dirent->d_name, "..") == 0)
165 : 0 : continue;
166 : :
167 : 0 : errno = 0;
168 : 0 : fd = strtol(dirent->d_name, &endptr, 10);
169 [ # # # # ]: 0 : if (errno != 0 || endptr[0] != '\0') {
170 : : printf("Error converting name fd %d %s:\n",
171 : : fd, dirent->d_name);
172 : 0 : continue;
173 : : }
174 : :
175 [ # # ]: 0 : if (fd == fdir || fd <= 2)
176 : 0 : continue;
177 : :
178 : 0 : close(fd);
179 : : }
180 : 0 : closedir(dir);
181 : : }
182 : : #endif
183 : : printf("Running binary with argv[]:");
184 [ # # ]: 0 : for (i = 0; i < num; i++)
185 : 0 : printf("'%s' ", argv_cpy[i]);
186 : : printf("\n");
187 : 0 : fflush(stdout);
188 : :
189 : : /* set the environment variable */
190 [ # # ]: 0 : if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0)
191 : 0 : rte_panic("Cannot export environment variable\n");
192 : :
193 : : strlcpy(path, "/proc/" self "/" exe, sizeof(path));
194 [ # # ]: 0 : if (execv(path, argv_cpy) < 0) {
195 [ # # ]: 0 : if (errno == ENOENT) {
196 : : printf("Could not find '%s', is procfs mounted?\n",
197 : : path);
198 : : }
199 : 0 : rte_panic("Cannot exec: %s\n", strerror(errno));
200 : : }
201 : : }
202 : : /* parent process does a wait */
203 : : #ifdef RTE_LIB_PDUMP
204 : : #ifdef RTE_NET_RING
205 [ + + ]: 132 : if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
206 : 1 : rc = rte_thread_create(&thread, NULL, send_pkts, NULL);
207 [ - + ]: 1 : if (rc != 0) {
208 : 0 : rte_panic("Cannot start send pkts thread: %s\n",
209 : : strerror(rc));
210 : : }
211 : : }
212 : : #endif
213 : : #endif
214 : :
215 [ - + ]: 132 : while (wait(&status) != pid)
216 : : ;
217 : : #ifdef RTE_LIB_PDUMP
218 : : #ifdef RTE_NET_RING
219 [ + + ]: 132 : if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
220 : 1 : flag_for_send_pkts = 0;
221 : 1 : rte_thread_join(thread, NULL);
222 : : }
223 : : #endif
224 : : #endif
225 : 132 : return status;
226 : : }
227 : :
228 : : /* FreeBSD doesn't support file prefixes, so force compile failures for any
229 : : * tests attempting to use this function on FreeBSD.
230 : : */
231 : : #ifdef RTE_EXEC_ENV_LINUX
232 : : static inline char *
233 : 12 : get_current_prefix(char *prefix, int size)
234 : : {
235 : 12 : char path[PATH_MAX] = {0};
236 : 12 : char buf[PATH_MAX] = {0};
237 : :
238 : : /* get file for config (fd is always 3) */
239 : : snprintf(path, sizeof(path), "/proc/self/fd/%d", 3);
240 : :
241 : : /* return NULL on error */
242 [ + - ]: 12 : if (readlink(path, buf, sizeof(buf)) == -1)
243 : : return NULL;
244 : :
245 : : /* get the prefix */
246 : 12 : rte_basename(dirname(buf), prefix, size);
247 : :
248 : 12 : return prefix;
249 : : }
250 : : #endif
251 : :
252 : : #endif /* _PROCESS_H_ */
|