/** * Forks and runs the given application, waits for a maximum of timeout seconds for process to finish. * * @param argv The arguments values, the first one is the application path or name */ void bb_run_fork_wait(char** argv, int timeout) { check_handler(); // Fork and attempt to run given application pid_t ret = fork(); if (ret == 0) { // Fork went ok, child process replace bb_run_exec(argv); } else { if (ret > 0) { // Fork went ok, parent process continues bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], ret); pidlist_add(ret); //sleep until process finishes or timeout reached int i = 0; while (bb_is_running(ret) && ((i < timeout) || (timeout == 0)) && dowait) { usleep(1000000); i++; } //make a single attempt to kill the process if timed out, without waiting if (bb_is_running(ret)) { bb_stop(ret); } } else { // Fork failed bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]); return; } } return; }
/** * Forks and runs the given application, using an optional LD_LIBRARY_PATH. The * function then returns immediately. * stderr and stdout of the ran application is redirected to the parameter redirect. * stdin is redirected to /dev/null always. * * @param argv The arguments values, the first one is the program * @param ldpath The library path to be used if any (may be NULL) * @param redirect The file descriptor to redirect stdout/stderr to. Must be valid and open. * @return The childs process ID */ pid_t bb_run_fork_ld_redirect(char **argv, char *ldpath, int redirect) { check_handler(); // Fork and attempt to run given application pid_t ret = fork(); if (ret == 0) { if (ldpath && *ldpath) { char *current_path = getenv("LD_LIBRARY_PATH"); /* Fork went ok, set environment if necessary */ if (current_path) { char *ldpath_new = malloc(strlen(ldpath) + 1 + strlen(current_path) + 1); if (ldpath_new) { strcpy(ldpath_new, ldpath); strcat(ldpath_new, ":"); strcat(ldpath_new, current_path); setenv("LD_LIBRARY_PATH", ldpath_new, 1); free(ldpath_new); } else { bb_log(LOG_WARNING, "Could not allocate memory for LD_LIBRARY_PATH\n"); } } else { setenv("LD_LIBRARY_PATH", ldpath, 1); } } //open /dev/null for stdin redirect int devnull = open("/dev/null", O_RDWR); //fail silently on error, nothing we can do about it anyway... if (devnull >= 0){dup2(devnull, STDIN_FILENO);} //redirect stdout and stderr to the given filenum. dup2(redirect, STDOUT_FILENO); dup2(redirect, STDERR_FILENO); close(devnull); //ok, all ready, now actually execute bb_run_exec(argv); } else { if (ret > 0) { // Fork went ok, parent process continues bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], ret); pidlist_add(ret); } else { // Fork failed bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]); return 0; } } return ret; }
/** * Forks and runs the given application and waits for the process to finish * * @param argv The arguments values, the first one is the program * @param detached non-zero if the std in/output must be redirected to /dev/null, zero otherwise * @return Exit code of the program (between 0 and 255) or -1 on failure */ int bb_run_fork(char **argv, int detached) { int exitcode = -1; check_handler(); /* Fork and attempt to run given application */ pid_t pid = fork(); if (pid == 0) { /* child process after fork */ if (detached) { bb_run_exec_detached(argv); } else { bb_run_exec(argv); } } else if (pid > 0) { /* parent process after fork */ int status = 0; bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], pid); pidlist_add(pid); if (waitpid(pid, &status, 0) != -1) { if (WIFEXITED(status)) { /* program exited normally, return status */ exitcode = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { /* program was terminated by a signal */ exitcode = 128 + WTERMSIG(status); } } else { bb_log(LOG_ERR, "waitpid(%i) faild with %s\n", pid, strerror(errno)); } pidlist_remove(pid); } else { /* Fork failed */ bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]); } /* could not determine return value */ return exitcode; }
/** * Forks and runs the given application, using an optional LD_LIBRARY_PATH. The * function then returns immediately * * @param argv The arguments values, the first one is the program * @param ldpath The library path to be used if any (may be NULL) * @return The childs process ID */ pid_t bb_run_fork_ld(char **argv, char *ldpath) { check_handler(); // Fork and attempt to run given application pid_t ret = fork(); if (ret == 0) { if (ldpath && *ldpath) { char *current_path = getenv("LD_LIBRARY_PATH"); /* Fork went ok, set environment if necessary */ if (current_path) { char *ldpath_new = malloc(strlen(ldpath) + 1 + strlen(current_path) + 1); if (ldpath_new) { strcpy(ldpath_new, ldpath); strcat(ldpath_new, ":"); strcat(ldpath_new, current_path); setenv("LD_LIBRARY_PATH", ldpath_new, 1); free(ldpath_new); } else { bb_log(LOG_WARNING, "Could not allocate memory for LD_LIBRARY_PATH\n"); } } else { setenv("LD_LIBRARY_PATH", ldpath, 1); } } bb_run_exec(argv); } else { if (ret > 0) { // Fork went ok, parent process continues bb_log(LOG_INFO, "Process %s started, PID %i.\n", argv[0], ret); pidlist_add(ret); } else { // Fork failed bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]); return 0; } } return ret; }