vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Sat Sep 19 12:32:21 2020 +0300| [d549d93e402e56bd8780c33faa8c46258993c69d] | committer: Rémi Denis-Courmont
vlc_spawn: vector posix_spawn/fork code This adds vlc_spawn(), vlc_spawnp() and vlc_waitpid() to factor the common code around the posix_spawn() family. It is added as part of the plugin API so that core code can use it (namely vlc_getProxyUrl()), which would not be possible with a shared C source in modules/. Win32 back-end may be provided later, e.g. based on old vlc_execve() implementation, if/when this actually gets used on Windows. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d549d93e402e56bd8780c33faa8c46258993c69d --- include/vlc_spawn.h | 94 +++++++++++++++++++++++++++++++++ src/Makefile.am | 2 + src/libvlccore.sym | 3 ++ src/missing.c | 26 ++++++++++ src/posix/spawn.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 272 insertions(+) diff --git a/include/vlc_spawn.h b/include/vlc_spawn.h new file mode 100644 index 0000000000..2dd3d10b41 --- /dev/null +++ b/include/vlc_spawn.h @@ -0,0 +1,94 @@ +/***************************************************************************** + * vlc_spawn.h: Child process helpers + ***************************************************************************** + * Copyright © 2020 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifndef VLC_SPAWN_H +#define VLC_SPAWN_H 1 + +#include <sys/types.h> + +/** + * \defgroup spawn Process management + * \ingroup os + * @{ + */ + +/** + * Spawn a child process (by file name). + * + * This function creates a child process. For all practical purposes, it is + * identical to vlc_spawnp(), with one exception: vlc_spawn() does <b>not</b> + * look for the executable file name in the OS-defined search path. Instead the + * file name must be absolute. + * + * \param pid storage space for the child process identifier [OUT] + * \param path executable file path [IN] + * \param fdv file descriptor array [IN] + * \param argv NULL-terminated array of command line arguments [IN] + * + * \return 0 on success or a standard error code on failure + */ +VLC_API VLC_USED +int vlc_spawn(pid_t *pid, const char *file, const int *fdv, + const char *const *argv); + +/** + * Spawn a child process. + * + * This function creates a child process. The created process will run with the + * same environment and privileges as the calling process. + * + * An array of file descriptors must be provided for the child process: + * - fdv[0] is the standard input (or -1 for nul input), + * - fdv[1] is the standard output (or -1 for nul output), + * - fdv[2] is the standard error (or -1 to ignore). + * The array must have at least 4 elements and be terminated by -1. + * Some platforms will ignore file descriptors other than the three standard + * ones, so those should not be used in code intended to be portable. + * + * vlc_waitpid() must be called to collect outstanding system resources + * after the child process terminates. + * + * \param pid storage space for the child process identifier [OUT] + * \param path executable path [IN] + * \param fdv file descriptor array [IN] + * \param argv NULL-terminated array of command line arguments [IN] + * + * \return 0 on success or a standard error code on failure + */ +VLC_API VLC_USED +int vlc_spawnp(pid_t *pid, const char *path, const int *fdv, + const char *const *argv); + +/** + * Waits for a child process. + * + * This function waits until a child process created by vlc_spawn() or + * vlc_spawnp() has completed and releases any associated system resource. + * + * \param pid process identifier as returned by vlc_spawn() or vlc_spawnp() + * + * \return This function returns the process exit code. + */ +VLC_API +int vlc_waitpid(pid_t pid); + +/** @} */ + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 51d8600e28..d8196fca61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,6 +91,7 @@ pluginsinclude_HEADERS = \ ../include/vlc_services_discovery.h \ ../include/vlc_sort.h \ ../include/vlc_sout.h \ + ../include/vlc_spawn.h \ ../include/vlc_spu.h \ ../include/vlc_stream.h \ ../include/vlc_stream_extractor.h \ @@ -478,6 +479,7 @@ libvlccore_la_SOURCES += \ posix/filesystem.c \ posix/plugin.c \ posix/rand.c \ + posix/spawn.c \ posix/timer.c if !HAVE_LINUX libvlccore_la_SOURCES += posix/wait.c diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 31fcd37cba..023203ea4f 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -450,6 +450,9 @@ vlc_accept vlc_send vlc_sendto vlc_sendmsg +vlc_spawn +vlc_spawnp +vlc_waitpid utf8_vfprintf var_AddCallback var_AddListCallback diff --git a/src/missing.c b/src/missing.c index 34283b63eb..45fddf177f 100644 --- a/src/missing.c +++ b/src/missing.c @@ -284,3 +284,29 @@ noreturn void vlc_control_cancel (vlc_cleanup_t *cleaner) vlc_assert_unreachable (); } #endif + +#include <errno.h> +#include <vlc_spawn.h> + +VLC_WEAK +int vlc_spawn(pid_t *pid, const char *file, const int *fds, + const char *const *args) +{ + (void) pid; (void) file; (void) fds; (void) args; + return ENOSYS; +} + +VLC_WEAK +int vlc_spawnp(pid_t *pid, const char *path, const int *fds, + const char *const *args) +{ + (void) pid; (void) path; (void) fds; (void) args; + return ENOSYS; +} + +VLC_WEAK +int vlc_waitpid(pid_t pid) +{ + (void) pid; + vlc_assert_unreachable(); +} diff --git a/src/posix/spawn.c b/src/posix/spawn.c new file mode 100644 index 0000000000..774c6cb6cb --- /dev/null +++ b/src/posix/spawn.c @@ -0,0 +1,147 @@ +/***************************************************************************** + * spawn.c + ***************************************************************************** + * Copyright (C) 2008, 2020 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <signal.h> +#include <sys/wait.h> + +#include <vlc_common.h> +#include <vlc_spawn.h> + +#if (_POSIX_SPAWN >= 0) +#include <spawn.h> + +extern char **environ; + +static int vlc_spawn_inner(pid_t *restrict pid, const char *path, + const int *fdv, const char *const *argv, + bool search) +{ + posix_spawnattr_t attr; + posix_spawn_file_actions_t fas; + char **vargv; + size_t argc = 0; + int err; + + assert(pid != NULL); + assert(path != NULL); + assert(fdv != NULL); + assert(argv != NULL); + + err = posix_spawn_file_actions_init(&fas); + if (unlikely(err != 0)) + return err; + + for (int newfd = 0; newfd < 3 || fdv[newfd] != -1; newfd++) { + int oldfd = fdv[newfd]; + + if (oldfd == -1) + err = posix_spawn_file_actions_addopen(&fas, newfd, "/dev/null", + O_RDWR, 0644); + else + err = posix_spawn_file_actions_adddup2(&fas, oldfd, newfd); + + if (unlikely(err != 0)) { + posix_spawn_file_actions_destroy(&fas); + return err; + } + } + + posix_spawnattr_init(&attr); + { + sigset_t set; + + /* Unmask signals. */ + sigemptyset(&set); + posix_spawnattr_setsigmask(&attr, &set); + + /* Reset SIGPIPE handler (which VLC overrode). */ + sigaddset(&set, SIGPIPE); + posix_spawnattr_setsigdefault(&attr, &set); + } + posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF + | POSIX_SPAWN_SETSIGMASK); + + /* For hysterical raisins, POSIX uses non-const character pointers. + * We need to copy manually due to aliasing rules. + */ + while (argv[argc++] != NULL); + + vargv = malloc(sizeof (*argv) * argc); + if (unlikely(vargv == NULL)) { + err = errno; + goto out; + } + + for (size_t i = 0; i < argc; i++) + vargv[i] = (char *)argv[i]; + + if (search) + err = posix_spawnp(pid, path, &fas, &attr, vargv, environ); + else + err = posix_spawn(pid, path, &fas, &attr, vargv, environ); + +out: + free(vargv); + posix_spawnattr_destroy(&attr); + posix_spawn_file_actions_destroy(&fas); + return err; +} + +#else /* _POSIX_SPAWN */ + +static int vlc_spawn_inner(pid_t *restrict pid, const char *path, + const int *fdv, const char *const *argv, + bool search) +{ + (void) pid; (void) path; (void) fdv; (void) argv; (void) search; +} + +#endif /* _POSIX_SPAWN */ + +int vlc_spawnp(pid_t *restrict pid, const char *path, + const int *fdv, const char *const *argv) +{ + return vlc_spawn_inner(pid, path, fdv, argv, true); +} + +int vlc_spawn(pid_t *restrict pid, const char *file, + const int *fdv, const char *const *argv) +{ + return vlc_spawn_inner(pid, file, fdv, argv, false); +} + +int vlc_waitpid(pid_t pid) +{ + int status; + + while (waitpid(pid, &status, 0) == -1) + assert(errno != ECHILD && errno != EINVAL); + + return status; +} _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
