Plugins now run in a forked process for extra resliance.
This commit is contained in:
parent
49b8b30ab7
commit
f269f1961b
@ -1,6 +1,10 @@
|
||||
# ChangeLog for Gentoo System Intialization ("rc") scripts
|
||||
# Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2
|
||||
|
||||
20 Apr 2007; Roy Marples <uberlord@gentoo.org>:
|
||||
|
||||
Plugins now run in a forked process for extra resliance.
|
||||
|
||||
17 Apr 2007; Roy Marples <uberlord@gentoo.org>:
|
||||
|
||||
Fix bridge, vlan and bonding modules to work together, #174792.
|
||||
|
@ -15,6 +15,9 @@
|
||||
|
||||
#define SOFTLEVEL RC_SVCDIR "softlevel"
|
||||
|
||||
/* File stream used for plugins to write environ vars to */
|
||||
FILE *rc_environ_fd = NULL;
|
||||
|
||||
static const char *rc_service_state_names[] = {
|
||||
"started",
|
||||
"stopped",
|
||||
|
@ -6,6 +6,8 @@
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -43,12 +45,7 @@ void rc_plugin_load (void)
|
||||
files = rc_ls_dir (NULL, RC_PLUGINDIR, 0);
|
||||
STRLIST_FOREACH (files, file, i) {
|
||||
char *p = rc_strcatpaths (RC_PLUGINDIR, file, NULL);
|
||||
/*
|
||||
* We load the use RTLD_NOW so that we know it works
|
||||
* as if we have any unknown symbols when we run then the
|
||||
* program bails out in rc_plugin_run which is very very bad.
|
||||
*/
|
||||
void *h = dlopen (p, RTLD_NOW);
|
||||
void *h = dlopen (p, RTLD_LAZY);
|
||||
char *func;
|
||||
void *f;
|
||||
int len;
|
||||
@ -94,9 +91,67 @@ void rc_plugin_run (rc_hook_t hook, const char *value)
|
||||
plugin_t *plugin = plugins;
|
||||
|
||||
while (plugin) {
|
||||
if (plugin->hook)
|
||||
plugin->hook (hook, value);
|
||||
if (plugin->hook) {
|
||||
int i;
|
||||
int flags;
|
||||
int pfd[2];
|
||||
pid_t pid;
|
||||
|
||||
/* We create a pipe so that plugins can affect our environment
|
||||
* vars, which in turn influence our scripts. */
|
||||
if (pipe (pfd) == -1) {
|
||||
eerror ("pipe: %s", strerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stop any scripts from inheriting us.
|
||||
* This is actually quite important as without this, the splash
|
||||
* plugin will probably hang when running in silent mode. */
|
||||
for (i = 0; i < 2; i++)
|
||||
if ((flags = fcntl (pfd[i], F_GETFD, 0)) < 0 ||
|
||||
fcntl (pfd[i], F_SETFD, flags | FD_CLOEXEC) < 0)
|
||||
eerror ("fcntl: %s", strerror (errno));
|
||||
|
||||
/* We run the plugin in a new process so we never crash
|
||||
* or otherwise affected by it */
|
||||
if ((pid = fork ()) == -1) {
|
||||
eerror ("fork: %s", strerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
int retval;
|
||||
|
||||
close (pfd[0]);
|
||||
rc_environ_fd = fdopen (pfd[1], "w");
|
||||
retval = plugin->hook (hook, value);
|
||||
fclose (rc_environ_fd);
|
||||
rc_environ_fd = NULL;
|
||||
_exit (retval);
|
||||
} else {
|
||||
char buffer[RC_LINEBUFFER];
|
||||
char *token;
|
||||
char *p;
|
||||
|
||||
close (pfd[1]);
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
/* Not the best implementation in the world.
|
||||
* We should be able to handle >1 env var.
|
||||
* Maybe split the strings with a NULL character? */
|
||||
while (read (pfd[0], buffer, sizeof (buffer)) > 0) {
|
||||
p = buffer;
|
||||
token = strsep (&p, "=");
|
||||
if (token) {
|
||||
unsetenv (token);
|
||||
if (p)
|
||||
setenv (token, p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
close (pfd[0]);
|
||||
}
|
||||
}
|
||||
plugin = plugin->next;
|
||||
}
|
||||
}
|
||||
|
3
src/rc.c
3
src/rc.c
@ -1120,8 +1120,7 @@ interactive_option:
|
||||
}
|
||||
|
||||
/* Wait for our services to finish */
|
||||
if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
|
||||
wait_for_services ();
|
||||
wait_for_services ();
|
||||
|
||||
rc_plugin_run (rc_hook_runlevel_start_out, runlevel);
|
||||
|
||||
|
4
src/rc.h
4
src/rc.h
@ -149,6 +149,10 @@ typedef enum
|
||||
rc_hook_service_start_out
|
||||
} rc_hook_t;
|
||||
|
||||
/* Plugins should write FOO=BAR to this fd to set any environment variables
|
||||
* they wish. At this time we only support the setting of one env var. */
|
||||
extern FILE *rc_environ_fd;
|
||||
|
||||
/* RC utility functions.
|
||||
Although not directly related to RC in general, they are used by RC
|
||||
itself and the supporting applications. */
|
||||
|
Loading…
Reference in New Issue
Block a user