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
|
# 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.
|
||||||
|
@ -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",
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
src/rc.c
1
src/rc.c
@ -1120,7 +1120,6 @@ 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);
|
||||||
|
4
src/rc.h
4
src/rc.h
@ -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. */
|
||||||
|
Loading…
Reference in New Issue
Block a user