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