xref: /dpdk/app/test/process.h (revision b3ce7891ad386310abab56352053a46ba06ca72f)
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
add_parameter_allow(char ** argv,int max_capacity)41 add_parameter_allow(char **argv, int max_capacity)
42 {
43 	struct rte_devargs *devargs;
44 	int count = 0;
45 
46 	RTE_EAL_DEVARGS_FOREACH(NULL, devargs) {
47 		if (strlen(devargs->name) == 0)
48 			continue;
49 
50 		if (devargs->data == NULL || strlen(devargs->data) == 0) {
51 			if (asprintf(&argv[count], PREFIX_ALLOW"%s", devargs->name) < 0)
52 				break;
53 		} else {
54 			if (asprintf(&argv[count], PREFIX_ALLOW"%s,%s",
55 					 devargs->name, devargs->data) < 0)
56 				break;
57 		}
58 
59 		if (++count == max_capacity)
60 			break;
61 	}
62 
63 	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
process_dup(const char * const argv[],int numargs,const char * env_value)73 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 	pid_t pid = fork();
89 	if (pid < 0)
90 		return -1;
91 	else if (pid == 0) {
92 		allow_num = rte_devargs_type_count(RTE_DEVTYPE_ALLOWED);
93 		argv_num = numargs + allow_num + 1;
94 		argv_cpy = calloc(argv_num, sizeof(char *));
95 		if (!argv_cpy)
96 			rte_panic("Memory allocation failed\n");
97 
98 		/* make a copy of the arguments to be passed to exec */
99 		for (i = 0; i < numargs; i++) {
100 			argv_cpy[i] = strdup(argv[i]);
101 			if (argv_cpy[i] == NULL)
102 				rte_panic("Error dup args\n");
103 		}
104 		if (allow_num > 0)
105 			num = add_parameter_allow(&argv_cpy[i], allow_num);
106 		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 			dir = opendir(procdir);
121 			if (dir == NULL) {
122 				rte_panic("Error opening %s: %s\n", procdir,
123 						strerror(errno));
124 			}
125 
126 			fdir = dirfd(dir);
127 			if (fdir < 0) {
128 				status = errno;
129 				closedir(dir);
130 				rte_panic("Error %d obtaining fd for dir %s: %s\n",
131 						fdir, procdir,
132 						strerror(status));
133 			}
134 
135 			while ((dirent = readdir(dir)) != NULL) {
136 
137 				if (strcmp(dirent->d_name, ".") == 0 ||
138 					strcmp(dirent->d_name, "..") == 0)
139 					continue;
140 
141 				errno = 0;
142 				fd = strtol(dirent->d_name, &endptr, 10);
143 				if (errno != 0 || endptr[0] != '\0') {
144 					printf("Error converting name fd %d %s:\n",
145 						fd, dirent->d_name);
146 					continue;
147 				}
148 
149 				if (fd == fdir || fd <= 2)
150 					continue;
151 
152 				close(fd);
153 			}
154 			closedir(dir);
155 		}
156 #endif
157 		printf("Running binary with argv[]:");
158 		for (i = 0; i < num; i++)
159 			printf("'%s' ", argv_cpy[i]);
160 		printf("\n");
161 		fflush(stdout);
162 
163 		/* set the environment variable */
164 		if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0)
165 			rte_panic("Cannot export environment variable\n");
166 
167 		strlcpy(path, "/proc/" self "/" exe, sizeof(path));
168 		if (execv(path, argv_cpy) < 0) {
169 			if (errno == ENOENT) {
170 				printf("Could not find '%s', is procfs mounted?\n",
171 						path);
172 			}
173 			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 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
180 		rc = rte_thread_create(&thread, NULL, send_pkts, NULL);
181 		if (rc != 0) {
182 			rte_panic("Cannot start send pkts thread: %s\n",
183 				  strerror(rc));
184 		}
185 	}
186 #endif
187 #endif
188 
189 	while (wait(&status) != pid)
190 		;
191 #ifdef RTE_LIB_PDUMP
192 #ifdef RTE_NET_RING
193 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
194 		flag_for_send_pkts = 0;
195 		rte_thread_join(thread, NULL);
196 	}
197 #endif
198 #endif
199 	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 *
get_current_prefix(char * prefix,int size)207 get_current_prefix(char *prefix, int size)
208 {
209 	char path[PATH_MAX] = {0};
210 	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 	if (readlink(path, buf, sizeof(buf)) == -1)
217 		return NULL;
218 
219 	/* get the prefix */
220 	snprintf(prefix, size, "%s", basename(dirname(buf)));
221 
222 	return prefix;
223 }
224 #endif
225 
226 #endif /* _PROCESS_H_ */
227