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 : :
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 : :
40 : : static int
41 : 0 : add_parameter_allow(char **argv, int max_capacity)
42 : : {
43 : : struct rte_devargs *devargs;
44 : : int count = 0;
45 : :
46 [ # # ]: 0 : RTE_EAL_DEVARGS_FOREACH(NULL, devargs) {
47 [ # # ]: 0 : if (strlen(devargs->name) == 0)
48 : 0 : continue;
49 : :
50 [ # # # # ]: 0 : if (devargs->data == NULL || strlen(devargs->data) == 0) {
51 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_ALLOW"%s", devargs->name) < 0)
52 : : break;
53 : : } else {
54 [ # # ]: 0 : if (asprintf(&argv[count], PREFIX_ALLOW"%s,%s",
55 : 0 : devargs->name, devargs->data) < 0)
56 : : break;
57 : : }
58 : :
59 [ # # ]: 0 : if (++count == max_capacity)
60 : : break;
61 : : }
62 : :
63 : 0 : return count;
64 : : }
65 : :
66 : : /*
67 : : * launches a second copy of the test process using the given argv parameters,
68 : : * which should include argv[0] as the process name. To identify in the
69 : : * subprocess the source of the call, the env_value parameter is set in the
70 : : * environment as $RTE_TEST
71 : : */
72 : : static inline int
73 : 126 : process_dup(const char *const argv[], int numargs, const char *env_value)
74 : : {
75 : : int num = 0;
76 : : char **argv_cpy;
77 : : int allow_num;
78 : : int argv_num;
79 : : int i, status;
80 : : char path[32];
81 : : #ifdef RTE_LIB_PDUMP
82 : : #ifdef RTE_NET_RING
83 : : rte_thread_t thread;
84 : : int rc;
85 : : #endif
86 : : #endif
87 : :
88 : 126 : pid_t pid = fork();
89 [ + - ]: 126 : if (pid < 0)
90 : : return -1;
91 [ - + ]: 126 : else if (pid == 0) {
92 : 0 : allow_num = rte_devargs_type_count(RTE_DEVTYPE_ALLOWED);
93 : 0 : argv_num = numargs + allow_num + 1;
94 : 0 : argv_cpy = calloc(argv_num, sizeof(char *));
95 [ # # ]: 0 : if (!argv_cpy)
96 : 0 : rte_panic("Memory allocation failed\n");
97 : :
98 : : /* make a copy of the arguments to be passed to exec */
99 [ # # ]: 0 : for (i = 0; i < numargs; i++) {
100 : 0 : argv_cpy[i] = strdup(argv[i]);
101 [ # # ]: 0 : if (argv_cpy[i] == NULL)
102 : 0 : rte_panic("Error dup args\n");
103 : : }
104 [ # # ]: 0 : if (allow_num > 0)
105 : 0 : num = add_parameter_allow(&argv_cpy[i], allow_num);
106 : 0 : num += numargs;
107 : :
108 : : #ifdef RTE_EXEC_ENV_LINUX
109 : : {
110 : : const char *procdir = "/proc/" self "/fd/";
111 : : struct dirent *dirent;
112 : : char *endptr;
113 : : int fd, fdir;
114 : : DIR *dir;
115 : :
116 : : /* close all open file descriptors, check /proc/self/fd
117 : : * to only call close on open fds. Exclude fds 0, 1 and
118 : : * 2
119 : : */
120 : 0 : dir = opendir(procdir);
121 [ # # ]: 0 : if (dir == NULL) {
122 : 0 : rte_panic("Error opening %s: %s\n", procdir,
123 : : strerror(errno));
124 : : }
125 : :
126 : 0 : fdir = dirfd(dir);
127 [ # # ]: 0 : if (fdir < 0) {
128 : 0 : status = errno;
129 : 0 : closedir(dir);
130 : 0 : rte_panic("Error %d obtaining fd for dir %s: %s\n",
131 : : fdir, procdir,
132 : : strerror(status));
133 : : }
134 : :
135 [ # # ]: 0 : while ((dirent = readdir(dir)) != NULL) {
136 : :
137 [ # # ]: 0 : if (strcmp(dirent->d_name, ".") == 0 ||
138 [ # # ]: 0 : strcmp(dirent->d_name, "..") == 0)
139 : 0 : continue;
140 : :
141 : 0 : errno = 0;
142 : 0 : fd = strtol(dirent->d_name, &endptr, 10);
143 [ # # # # ]: 0 : if (errno != 0 || endptr[0] != '\0') {
144 : : printf("Error converting name fd %d %s:\n",
145 : : fd, dirent->d_name);
146 : 0 : continue;
147 : : }
148 : :
149 [ # # ]: 0 : if (fd == fdir || fd <= 2)
150 : 0 : continue;
151 : :
152 : 0 : close(fd);
153 : : }
154 : 0 : closedir(dir);
155 : : }
156 : : #endif
157 : : printf("Running binary with argv[]:");
158 [ # # ]: 0 : for (i = 0; i < num; i++)
159 : 0 : printf("'%s' ", argv_cpy[i]);
160 : : printf("\n");
161 : 0 : fflush(stdout);
162 : :
163 : : /* set the environment variable */
164 [ # # ]: 0 : if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0)
165 : 0 : rte_panic("Cannot export environment variable\n");
166 : :
167 : : strlcpy(path, "/proc/" self "/" exe, sizeof(path));
168 [ # # ]: 0 : if (execv(path, argv_cpy) < 0) {
169 [ # # ]: 0 : if (errno == ENOENT) {
170 : : printf("Could not find '%s', is procfs mounted?\n",
171 : : path);
172 : : }
173 : 0 : rte_panic("Cannot exec: %s\n", strerror(errno));
174 : : }
175 : : }
176 : : /* parent process does a wait */
177 : : #ifdef RTE_LIB_PDUMP
178 : : #ifdef RTE_NET_RING
179 [ + + ]: 126 : if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
180 : 1 : rc = rte_thread_create(&thread, NULL, send_pkts, NULL);
181 [ - + ]: 1 : if (rc != 0) {
182 : 0 : rte_panic("Cannot start send pkts thread: %s\n",
183 : : strerror(rc));
184 : : }
185 : : }
186 : : #endif
187 : : #endif
188 : :
189 [ - + ]: 126 : while (wait(&status) != pid)
190 : : ;
191 : : #ifdef RTE_LIB_PDUMP
192 : : #ifdef RTE_NET_RING
193 [ + + ]: 126 : if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
194 : 1 : flag_for_send_pkts = 0;
195 : 1 : rte_thread_join(thread, NULL);
196 : : }
197 : : #endif
198 : : #endif
199 : 126 : return status;
200 : : }
201 : :
202 : : /* FreeBSD doesn't support file prefixes, so force compile failures for any
203 : : * tests attempting to use this function on FreeBSD.
204 : : */
205 : : #ifdef RTE_EXEC_ENV_LINUX
206 : : static char *
207 : 12 : get_current_prefix(char *prefix, int size)
208 : : {
209 : 12 : char path[PATH_MAX] = {0};
210 : 12 : char buf[PATH_MAX] = {0};
211 : :
212 : : /* get file for config (fd is always 3) */
213 : : snprintf(path, sizeof(path), "/proc/self/fd/%d", 3);
214 : :
215 : : /* return NULL on error */
216 [ + - ]: 12 : if (readlink(path, buf, sizeof(buf)) == -1)
217 : : return NULL;
218 : :
219 : : /* get the prefix */
220 : 12 : snprintf(prefix, size, "%s", basename(dirname(buf)));
221 : :
222 : 12 : return prefix;
223 : : }
224 : : #endif
225 : :
226 : : #endif /* _PROCESS_H_ */
|