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 #include <libgen.h> /* basename et al */ 11 #include <stdlib.h> /* NULL */ 12 #include <string.h> /* strerror */ 13 #include <unistd.h> /* readlink */ 14 #include <dirent.h> 15 #include <sys/wait.h> 16 17 #include <rte_string_fns.h> /* strlcpy */ 18 19 #ifdef RTE_EXEC_ENV_FREEBSD 20 #define self "curproc" 21 #define exe "file" 22 #else 23 #define self "self" 24 #define exe "exe" 25 #endif 26 27 #ifdef RTE_LIBRTE_PDUMP 28 #include <pthread.h> 29 extern void *send_pkts(void *empty); 30 extern uint16_t flag_for_send_pkts; 31 #endif 32 33 /* 34 * launches a second copy of the test process using the given argv parameters, 35 * which should include argv[0] as the process name. To identify in the 36 * subprocess the source of the call, the env_value parameter is set in the 37 * environment as $RTE_TEST 38 */ 39 static inline int 40 process_dup(const char *const argv[], int numargs, const char *env_value) 41 { 42 int num; 43 char *argv_cpy[numargs + 1]; 44 int i, status; 45 char path[32]; 46 #ifdef RTE_LIBRTE_PDUMP 47 pthread_t thread; 48 #endif 49 50 pid_t pid = fork(); 51 if (pid < 0) 52 return -1; 53 else if (pid == 0) { 54 /* make a copy of the arguments to be passed to exec */ 55 for (i = 0; i < numargs; i++) 56 argv_cpy[i] = strdup(argv[i]); 57 argv_cpy[i] = NULL; 58 num = numargs; 59 60 #ifdef RTE_EXEC_ENV_LINUX 61 { 62 const char *procdir = "/proc/" self "/fd/"; 63 struct dirent *dirent; 64 char *endptr; 65 int fd, fdir; 66 DIR *dir; 67 68 /* close all open file descriptors, check /proc/self/fd 69 * to only call close on open fds. Exclude fds 0, 1 and 70 * 2 71 */ 72 dir = opendir(procdir); 73 if (dir == NULL) { 74 rte_panic("Error opening %s: %s\n", procdir, 75 strerror(errno)); 76 } 77 78 fdir = dirfd(dir); 79 if (fdir < 0) { 80 status = errno; 81 closedir(dir); 82 rte_panic("Error %d obtaining fd for dir %s: %s\n", 83 fdir, procdir, 84 strerror(status)); 85 } 86 87 while ((dirent = readdir(dir)) != NULL) { 88 errno = 0; 89 fd = strtol(dirent->d_name, &endptr, 10); 90 if (errno != 0 || endptr[0] != '\0') { 91 printf("Error converting name fd %d %s:\n", 92 fd, dirent->d_name); 93 continue; 94 } 95 96 if (fd == fdir || fd <= 2) 97 continue; 98 99 close(fd); 100 } 101 closedir(dir); 102 } 103 #endif 104 printf("Running binary with argv[]:"); 105 for (i = 0; i < num; i++) 106 printf("'%s' ", argv_cpy[i]); 107 printf("\n"); 108 109 /* set the environment variable */ 110 if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0) 111 rte_panic("Cannot export environment variable\n"); 112 113 strlcpy(path, "/proc/" self "/" exe, sizeof(path)); 114 if (execv(path, argv_cpy) < 0) { 115 if (errno == ENOENT) { 116 printf("Could not find '%s', is procfs mounted?\n", 117 path); 118 } 119 rte_panic("Cannot exec: %s\n", strerror(errno)); 120 } 121 } 122 /* parent process does a wait */ 123 #ifdef RTE_LIBRTE_PDUMP 124 if ((strcmp(env_value, "run_pdump_server_tests") == 0)) 125 pthread_create(&thread, NULL, &send_pkts, NULL); 126 #endif 127 128 while (wait(&status) != pid) 129 ; 130 #ifdef RTE_LIBRTE_PDUMP 131 if ((strcmp(env_value, "run_pdump_server_tests") == 0)) { 132 flag_for_send_pkts = 0; 133 pthread_join(thread, NULL); 134 } 135 #endif 136 return status; 137 } 138 139 /* FreeBSD doesn't support file prefixes, so force compile failures for any 140 * tests attempting to use this function on FreeBSD. 141 */ 142 #ifdef RTE_EXEC_ENV_LINUX 143 static char * 144 get_current_prefix(char *prefix, int size) 145 { 146 char path[PATH_MAX] = {0}; 147 char buf[PATH_MAX] = {0}; 148 149 /* get file for config (fd is always 3) */ 150 snprintf(path, sizeof(path), "/proc/self/fd/%d", 3); 151 152 /* return NULL on error */ 153 if (readlink(path, buf, sizeof(buf)) == -1) 154 return NULL; 155 156 /* get the prefix */ 157 snprintf(prefix, size, "%s", basename(dirname(buf))); 158 159 return prefix; 160 } 161 #endif 162 163 #endif /* _PROCESS_H_ */ 164