From 11e33e81c855395cbd931e99f7452ed6b3fef357 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Fri, 28 Mar 2008 08:42:05 +0000 Subject: Remove rc_service_start/stop from librc as they block and unmask signals. The application may not wish this behaviour and should fork/exec the service itself. --- man/rc_service.3 | 15 +------ src/includes/rc-misc.h | 4 ++ src/librc/librc.c | 89 ---------------------------------------- src/librc/librc.h | 2 - src/librc/rc.h | 10 ----- src/librc/rc.map | 2 - src/rc/rc-misc.c | 63 ++++++++++++++++++++++++++++ src/rc/rc.c | 55 ++++++++++++++----------- src/rc/runscript.c | 10 ++--- src/test/librc.funcs.hidden.list | 2 - src/test/rc.funcs.list | 4 -- 11 files changed, 103 insertions(+), 153 deletions(-) diff --git a/man/rc_service.3 b/man/rc_service.3 index a716857f..9a48db8d 100644 --- a/man/rc_service.3 +++ b/man/rc_service.3 @@ -31,11 +31,10 @@ .Nm rc_service_mark , rc_service_extra_commands , rc_service_plugable , .Nm rc_service_resolve , rc_service_schedule_start , rc_services_scheduled_by , .Nm rc_service_schedule_clear , rc_service_state , -.Nm rc_service_start , rc_service_stop , .Nm rc_service_started_daemon , rc_service_value_get , rc_service_value_set , .Nm rc_services_in_runlevel , rc_services_in_state , rc_services_scheduled , .Nm rc_service_daemons_crashed -.Nd functions to start, stop and query OpenRC services +.Nd functions to query OpenRC services .Sh LIBRARY Run Command library (librc, -lrc) .Sh SYNOPSIS @@ -66,8 +65,6 @@ Run Command library (librc, -lrc) .Ft "RC_STRINGLIST *" Fn rc_services_scheduled_by "const char *service" .Ft bool Fn rc_service_schedule_clear "const char *service" .Ft RC_SERVICE Fn rc_service_state "const char *service" -.Ft pid_t Fn rc_service_start "const char *service" -.Ft pid_t Fn rc_service_stop "const char *service" .Ft bool Fo rc_service_started_daemon .Fa "const char *service" .Fa "const char *exec" @@ -176,16 +173,6 @@ clears these scheduled services for .Fa service . The return value is a bitmask, where more than one state can apply. .Pp -.Fn rc_service_start -starts -.Fa service , -returning the pid of new process. -.Pp -.Fn rc_service_stop -stops -.Fa service , -returning the pid of new process. -.Pp .Fn rc_service_started_daemon checks to see if .Fa service diff --git a/src/includes/rc-misc.h b/src/includes/rc-misc.h index 0906e3ea..70850161 100644 --- a/src/includes/rc-misc.h +++ b/src/includes/rc-misc.h @@ -196,6 +196,10 @@ void env_filter(void); void env_config(void); bool service_plugable(const char *service); int signal_setup(int sig, void (*handler)(int)); +pid_t exec_service(const char *, const char *); + +#define service_start(service) exec_service(service, "start"); +#define service_stop(service) exec_service(service, "stop"); /* basename_c never modifies the argument. As such, if there is a trailing * slash then an empty string is returned. */ diff --git a/src/librc/librc.c b/src/librc/librc.c index 5d4826c9..13220d2f 100644 --- a/src/librc/librc.c +++ b/src/librc/librc.c @@ -673,95 +673,6 @@ bool rc_service_value_set(const char *service, const char *option, } librc_hidden_def(rc_service_value_set) -static pid_t _exec_service(const char *service, const char *arg) -{ - char *file; - char fifo[PATH_MAX]; - pid_t pid = -1; - sigset_t full; - sigset_t old; - struct sigaction sa; - - file = rc_service_resolve(service); - if (! exists(file)) { - rc_service_mark(service, RC_SERVICE_STOPPED); - free(file); - return 0; - } - - /* We create a fifo so that other services can wait until we complete */ - snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", - basename_c(service)); - if (mkfifo(fifo, 0600) != 0 && errno != EEXIST) { - free(file); - return -1; - } - - /* We need to block signals until we have forked */ - memset(&sa, 0, sizeof (sa)); - sa.sa_handler = SIG_DFL; - sigemptyset(&sa.sa_mask); - sigfillset(&full); - sigprocmask(SIG_SETMASK, &full, &old); - - if ((pid = fork()) == 0) { - /* Restore default handlers */ - sigaction(SIGCHLD, &sa, NULL); - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGQUIT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGUSR1, &sa, NULL); - sigaction(SIGWINCH, &sa, NULL); - - /* Unmask signals */ - sigprocmask(SIG_SETMASK, &old, NULL); - - /* Safe to run now */ - execl(file, file, arg, (char *) NULL); - fprintf(stderr, "unable to exec `%s': %s\n", - file, strerror(errno)); - unlink(fifo); - _exit(EXIT_FAILURE); - } - - if (pid == -1) - fprintf(stderr, "fork: %s\n",strerror (errno)); - - sigprocmask(SIG_SETMASK, &old, NULL); - - free(file); - - return pid; -} - -pid_t rc_service_stop(const char *service) -{ - RC_SERVICE state = rc_service_state(service); - - if (state & RC_SERVICE_FAILED) - return -1; - - if (state & RC_SERVICE_STOPPED) - return 0; - - return _exec_service(service, "stop"); -} -librc_hidden_def(rc_service_stop) - -pid_t rc_service_start(const char *service) -{ - RC_SERVICE state = rc_service_state(service); - - if (state & RC_SERVICE_FAILED) - return -1; - - if (! state & RC_SERVICE_STOPPED) - return 0; - - return _exec_service(service, "start"); -} -librc_hidden_def(rc_service_start) bool rc_service_schedule_start(const char *service, const char *service_to_start) diff --git a/src/librc/librc.h b/src/librc/librc.h index b5e9cabd..353b5923 100644 --- a/src/librc/librc.h +++ b/src/librc/librc.h @@ -104,8 +104,6 @@ librc_hidden_proto(rc_service_mark) librc_hidden_proto(rc_service_resolve) librc_hidden_proto(rc_service_schedule_clear) librc_hidden_proto(rc_service_schedule_start) -librc_hidden_proto(rc_service_start) -librc_hidden_proto(rc_service_stop) librc_hidden_proto(rc_services_in_runlevel) librc_hidden_proto(rc_services_in_state) librc_hidden_proto(rc_services_scheduled) diff --git a/src/librc/rc.h b/src/librc/rc.h index 415963b4..04cdba4d 100644 --- a/src/librc/rc.h +++ b/src/librc/rc.h @@ -172,16 +172,6 @@ bool rc_service_schedule_clear(const char *); * @return state of the service */ RC_SERVICE rc_service_state(const char *); -/*! Start a service - * @param service to start - * @return pid of the service starting process */ -pid_t rc_service_start(const char *); - -/*! Stop a service - * @param service to stop - * @return pid of service stopping process */ -pid_t rc_service_stop(const char *); - /*! Check if the service started the daemon * @param service to check * @param exec to check diff --git a/src/librc/rc.map b/src/librc/rc.map index 845ae946..8a803f3d 100644 --- a/src/librc/rc.map +++ b/src/librc/rc.map @@ -32,8 +32,6 @@ global: rc_service_resolve; rc_service_schedule_clear; rc_service_schedule_start; - rc_service_start; - rc_service_stop; rc_services_in_runlevel; rc_services_in_state; rc_services_scheduled; diff --git a/src/rc/rc-misc.c b/src/rc/rc-misc.c index 32fe50e3..afe7893c 100644 --- a/src/rc/rc-misc.c +++ b/src/rc/rc-misc.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "einfo.h" #include "rc.h" @@ -310,3 +311,65 @@ int signal_setup(int sig, void (*handler)(int)) sa.sa_handler = handler; return sigaction(sig, &sa, NULL); } + +pid_t exec_service(const char *service, const char *arg) +{ + char *file; + char fifo[PATH_MAX]; + pid_t pid = -1; + sigset_t full; + sigset_t old; + struct sigaction sa; + + file = rc_service_resolve(service); + if (! exists(file)) { + rc_service_mark(service, RC_SERVICE_STOPPED); + free(file); + return 0; + } + + /* We create a fifo so that other services can wait until we complete */ + snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", + basename_c(service)); + if (mkfifo(fifo, 0600) != 0 && errno != EEXIST) { + free(file); + return -1; + } + + /* We need to block signals until we have forked */ + memset(&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sigfillset(&full); + sigprocmask(SIG_SETMASK, &full, &old); + + if ((pid = fork()) == 0) { + /* Restore default handlers */ + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGWINCH, &sa, NULL); + + /* Unmask signals */ + sigprocmask(SIG_SETMASK, &old, NULL); + + /* Safe to run now */ + execl(file, file, arg, (char *) NULL); + fprintf(stderr, "unable to exec `%s': %s\n", + file, strerror(errno)); + unlink(fifo); + _exit(EXIT_FAILURE); + } + + if (pid == -1) + fprintf(stderr, "fork: %s\n",strerror (errno)); + + sigprocmask(SIG_SETMASK, &old, NULL); + + free(file); + + return pid; +} diff --git a/src/rc/rc.c b/src/rc/rc.c index a6f58b4f..43bcb48e 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -771,6 +771,7 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle pid_t pid; RC_STRING *service, *svc1, *svc2; RC_STRINGLIST *deporder, *tmplist; + RC_SERVICE state; if (! types_n) { types_n = rc_stringlist_new(); @@ -779,12 +780,13 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle TAILQ_FOREACH_REVERSE(service, stop_services, rc_stringlist, entries) { - if (rc_service_state(service->value) & RC_SERVICE_STOPPED) + state = rc_service_state(service->value); + if (state & RC_SERVICE_STOPPED || state & RC_SERVICE_FAILED) continue; /* We always stop the service when in these runlevels */ if (going_down || ! start_services) { - pid = rc_service_stop(service->value); + pid = service_stop(service->value); if (pid > 0 && ! parallel) rc_waitpid(pid); continue; @@ -832,7 +834,7 @@ static void do_stop_services(const char *newlevel, bool going_down, bool paralle } /* After all that we can finally stop the blighter! */ - pid = rc_service_stop(service->value); + pid = service_stop(service->value); if (pid > 0) { add_pid(pid); if (! parallel) { @@ -848,44 +850,47 @@ static void do_start_services(bool parallel) RC_STRING *service; pid_t pid; bool interactive = false; + RC_SERVICE state; if (! rc_yesno(getenv("EINFO_QUIET"))) interactive = exists(INTERACTIVE); TAILQ_FOREACH(service, start_services, entries) { - if (rc_service_state(service->value) & RC_SERVICE_STOPPED) { - if (! interactive) - interactive = want_interactive(); + state = rc_service_state(service->value); + if (!(state & RC_SERVICE_STOPPED) || state & RC_SERVICE_FAILED) + continue; + + if (! interactive) + interactive = want_interactive(); - if (interactive) { + if (interactive) { interactive_retry: - printf("\n"); - einfo("About to start the service %s", - service->value); - eindent(); - einfo("1) Start the service\t\t2) Skip the service"); - einfo("3) Continue boot process\t\t4) Exit to shell"); - eoutdent(); + printf("\n"); + einfo("About to start the service %s", + service->value); + eindent(); + einfo("1) Start the service\t\t2) Skip the service"); + einfo("3) Continue boot process\t\t4) Exit to shell"); + eoutdent(); interactive_option: - switch (read_key(true)) { + switch (read_key(true)) { case '1': break; case '2': continue; case '3': interactive = false; break; case '4': sulogin(true); goto interactive_retry; default: goto interactive_option; - } } + } - pid = rc_service_start(service->value); - - /* Remember the pid if we're running in parallel */ - if (pid > 0) { - add_pid(pid); + pid = service_start(service->value); - if (! parallel) { - rc_waitpid(pid); - remove_pid(pid); - } + /* Remember the pid if we're running in parallel */ + if (pid > 0) { + add_pid(pid); + + if (! parallel) { + rc_waitpid(pid); + remove_pid(pid); } } } diff --git a/src/rc/runscript.c b/src/rc/runscript.c index 8720c02f..421f432f 100644 --- a/src/rc/runscript.c +++ b/src/rc/runscript.c @@ -273,7 +273,7 @@ static void start_services(RC_STRINGLIST *list) { " when %s has started", svc->value, applet); } else - rc_service_start(svc->value); + service_start(svc->value); } } } @@ -727,7 +727,7 @@ static void svc_start(bool deps) if (! rc_runlevel_starting() && use_services) TAILQ_FOREACH(svc, use_services, entries) if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) { - pid_t pid = rc_service_start(svc->value); + pid_t pid = service_start(svc->value); if (! rc_conf_yesno("rc_parallel")) rc_waitpid(pid); } @@ -851,7 +851,7 @@ static void svc_start(bool deps) if (services) { TAILQ_FOREACH(svc, services, entries) if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) - rc_service_start(svc->value); + service_start(svc->value); rc_stringlist_free(services); services = NULL; } @@ -864,7 +864,7 @@ static void svc_start(bool deps) if (services) { TAILQ_FOREACH(svc2, services, entries) if (rc_service_state(svc2->value) & RC_SERVICE_STOPPED) - rc_service_start(svc2->value); + service_start(svc2->value); rc_stringlist_free(services); services = NULL; } @@ -939,7 +939,7 @@ static void svc_stop(bool deps) if (svcs & RC_SERVICE_STARTED || svcs & RC_SERVICE_INACTIVE) { - pid_t pid = rc_service_stop(svc->value); + pid_t pid = service_stop(svc->value); if (! rc_conf_yesno("rc_parallel")) rc_waitpid(pid); if (! tmplist) diff --git a/src/test/librc.funcs.hidden.list b/src/test/librc.funcs.hidden.list index a21e21e3..2ece066d 100644 --- a/src/test/librc.funcs.hidden.list +++ b/src/test/librc.funcs.hidden.list @@ -29,10 +29,8 @@ rc_service_mark rc_service_resolve rc_service_schedule_clear rc_service_schedule_start -rc_service_start rc_service_started_daemon rc_service_state -rc_service_stop rc_service_value_get rc_service_value_set rc_services_in_runlevel diff --git a/src/test/rc.funcs.list b/src/test/rc.funcs.list index 59dc215e..a10afc04 100644 --- a/src/test/rc.funcs.list +++ b/src/test/rc.funcs.list @@ -58,14 +58,10 @@ rc_service_schedule_clear rc_service_schedule_clear@@RC_1.0 rc_service_schedule_start rc_service_schedule_start@@RC_1.0 -rc_service_start -rc_service_start@@RC_1.0 rc_service_started_daemon rc_service_started_daemon@@RC_1.0 rc_service_state rc_service_state@@RC_1.0 -rc_service_stop -rc_service_stop@@RC_1.0 rc_service_value_get rc_service_value_get@@RC_1.0 rc_service_value_set -- cgit v1.2.3