Plugins now run in a forked process for extra resliance.

This commit is contained in:
Roy Marples 2007-04-20 09:39:47 +00:00
parent 49b8b30ab7
commit f269f1961b
5 changed files with 75 additions and 10 deletions

View File

@ -1,6 +1,10 @@
# ChangeLog for Gentoo System Intialization ("rc") scripts # ChangeLog for Gentoo System Intialization ("rc") scripts
# Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2 # 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>: 17 Apr 2007; Roy Marples <uberlord@gentoo.org>:
Fix bridge, vlan and bonding modules to work together, #174792. Fix bridge, vlan and bonding modules to work together, #174792.

View File

@ -15,6 +15,9 @@
#define SOFTLEVEL RC_SVCDIR "softlevel" #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[] = { static const char *rc_service_state_names[] = {
"started", "started",
"stopped", "stopped",

View File

@ -6,6 +6,8 @@
*/ */
#include <dlfcn.h> #include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -43,12 +45,7 @@ void rc_plugin_load (void)
files = rc_ls_dir (NULL, RC_PLUGINDIR, 0); files = rc_ls_dir (NULL, RC_PLUGINDIR, 0);
STRLIST_FOREACH (files, file, i) { STRLIST_FOREACH (files, file, i) {
char *p = rc_strcatpaths (RC_PLUGINDIR, file, NULL); char *p = rc_strcatpaths (RC_PLUGINDIR, file, NULL);
/* void *h = dlopen (p, RTLD_LAZY);
* 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);
char *func; char *func;
void *f; void *f;
int len; int len;
@ -94,9 +91,67 @@ void rc_plugin_run (rc_hook_t hook, const char *value)
plugin_t *plugin = plugins; plugin_t *plugin = plugins;
while (plugin) { while (plugin) {
if (plugin->hook) if (plugin->hook) {
plugin->hook (hook, value); 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; plugin = plugin->next;
} }
} }

View File

@ -1120,8 +1120,7 @@ interactive_option:
} }
/* Wait for our services to finish */ /* 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); rc_plugin_run (rc_hook_runlevel_start_out, runlevel);

View File

@ -149,6 +149,10 @@ typedef enum
rc_hook_service_start_out rc_hook_service_start_out
} rc_hook_t; } 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. /* RC utility functions.
Although not directly related to RC in general, they are used by RC Although not directly related to RC in general, they are used by RC
itself and the supporting applications. */ itself and the supporting applications. */