mirror of
https://github.com/openvswitch/ovs
synced 2025-09-03 15:55:19 +00:00
process: Factor code out of process_start() into helper functions.
An upcoming commit will add a new function that can also use these helper functions.
This commit is contained in:
@@ -119,6 +119,59 @@ process_escape_args(char **argv)
|
|||||||
return ds_cstr(&ds);
|
return ds_cstr(&ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare to start a process whose command-line arguments are given by the
|
||||||
|
* null-terminated 'argv' array. Returns 0 if successful, otherwise a
|
||||||
|
* positive errno value. */
|
||||||
|
static int
|
||||||
|
process_prestart(char **argv)
|
||||||
|
{
|
||||||
|
char *binary;
|
||||||
|
|
||||||
|
process_init();
|
||||||
|
|
||||||
|
/* Log the process to be started. */
|
||||||
|
if (VLOG_IS_DBG_ENABLED()) {
|
||||||
|
char *args = process_escape_args(argv);
|
||||||
|
VLOG_DBG("starting subprocess: %s", args);
|
||||||
|
free(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* execvp() will search PATH too, but the error in that case is more
|
||||||
|
* obscure, since it is only reported post-fork. */
|
||||||
|
binary = process_search_path(argv[0]);
|
||||||
|
if (!binary) {
|
||||||
|
VLOG_ERR("%s not found in PATH", argv[0]);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
free(binary);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates and returns a new struct process with the specified 'name' and
|
||||||
|
* 'pid'.
|
||||||
|
*
|
||||||
|
* This is racy unless SIGCHLD is blocked (and has been blocked since before
|
||||||
|
* the fork()) that created the subprocess. */
|
||||||
|
static struct process *
|
||||||
|
process_register(const char *name, pid_t pid)
|
||||||
|
{
|
||||||
|
struct process *p;
|
||||||
|
const char *slash;
|
||||||
|
|
||||||
|
assert(sigchld_is_blocked());
|
||||||
|
|
||||||
|
p = xcalloc(1, sizeof *p);
|
||||||
|
p->pid = pid;
|
||||||
|
slash = strrchr(name, '/');
|
||||||
|
p->name = xstrdup(slash ? slash + 1 : name);
|
||||||
|
p->exited = false;
|
||||||
|
|
||||||
|
list_push_back(&all_processes, &p->node);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/* Starts a subprocess with the arguments in the null-terminated argv[] array.
|
/* Starts a subprocess with the arguments in the null-terminated argv[] array.
|
||||||
* argv[0] is used as the name of the process. Searches the PATH environment
|
* argv[0] is used as the name of the process. Searches the PATH environment
|
||||||
* variable to find the program to execute.
|
* variable to find the program to execute.
|
||||||
@@ -137,28 +190,16 @@ process_start(char **argv,
|
|||||||
struct process **pp)
|
struct process **pp)
|
||||||
{
|
{
|
||||||
sigset_t oldsigs;
|
sigset_t oldsigs;
|
||||||
char *binary;
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int error;
|
||||||
|
|
||||||
*pp = NULL;
|
*pp = NULL;
|
||||||
process_init();
|
|
||||||
COVERAGE_INC(process_start);
|
COVERAGE_INC(process_start);
|
||||||
|
error = process_prestart(argv);
|
||||||
if (VLOG_IS_DBG_ENABLED()) {
|
if (error) {
|
||||||
char *args = process_escape_args(argv);
|
return error;
|
||||||
VLOG_DBG("starting subprocess: %s", args);
|
|
||||||
free(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* execvp() will search PATH too, but the error in that case is more
|
|
||||||
* obscure, since it is only reported post-fork. */
|
|
||||||
binary = process_search_path(argv[0]);
|
|
||||||
if (!binary) {
|
|
||||||
VLOG_ERR("%s not found in PATH", argv[0]);
|
|
||||||
return ENOENT;
|
|
||||||
}
|
|
||||||
free(binary);
|
|
||||||
|
|
||||||
block_sigchld(&oldsigs);
|
block_sigchld(&oldsigs);
|
||||||
fatal_signal_block();
|
fatal_signal_block();
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@@ -169,20 +210,9 @@ process_start(char **argv,
|
|||||||
return errno;
|
return errno;
|
||||||
} else if (pid) {
|
} else if (pid) {
|
||||||
/* Running in parent process. */
|
/* Running in parent process. */
|
||||||
struct process *p;
|
*pp = process_register(argv[0], pid);
|
||||||
const char *slash;
|
|
||||||
|
|
||||||
p = xcalloc(1, sizeof *p);
|
|
||||||
p->pid = pid;
|
|
||||||
slash = strrchr(argv[0], '/');
|
|
||||||
p->name = xstrdup(slash ? slash + 1 : argv[0]);
|
|
||||||
p->exited = false;
|
|
||||||
|
|
||||||
list_push_back(&all_processes, &p->node);
|
|
||||||
unblock_sigchld(&oldsigs);
|
|
||||||
fatal_signal_unblock();
|
fatal_signal_unblock();
|
||||||
|
unblock_sigchld(&oldsigs);
|
||||||
*pp = p;
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* Running in child process. */
|
/* Running in child process. */
|
||||||
@@ -406,6 +436,16 @@ is_member(int x, const int *array, size_t n)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
sigchld_is_blocked(void)
|
||||||
|
{
|
||||||
|
sigset_t sigs;
|
||||||
|
if (sigprocmask(SIG_SETMASK, NULL, &sigs)) {
|
||||||
|
ovs_fatal(errno, "sigprocmask");
|
||||||
|
}
|
||||||
|
return sigismember(&sigs, SIGCHLD);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
block_sigchld(sigset_t *oldsigs)
|
block_sigchld(sigset_t *oldsigs)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user