Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92662ddc44 | ||
|
|
1b6a35488d | ||
|
|
1eccb7f5e6 | ||
|
|
fe37fc9322 | ||
|
|
edf5f830e3 | ||
|
|
863e1a5c87 | ||
|
|
0b9c3c0803 | ||
|
|
a3c721b682 | ||
|
|
3f82d5b1a3 | ||
|
|
0b4732520f | ||
|
|
bbd3acfc67 | ||
|
|
910e3e2a0e | ||
|
|
5f04dcc951 | ||
|
|
8f52c64c37 | ||
|
|
09d405fb3e | ||
|
|
36e4e04ba9 | ||
|
|
eb8831a141 |
4
NEWS.md
4
NEWS.md
@@ -4,6 +4,10 @@ OpenRC NEWS
|
|||||||
This file will contain a list of notable changes for each release. Note
|
This file will contain a list of notable changes for each release. Note
|
||||||
the information in this file is in reverse order.
|
the information in this file is in reverse order.
|
||||||
|
|
||||||
|
## OpenRC 0.48
|
||||||
|
|
||||||
|
This release is a maintenance release; it has no user-facing changes.
|
||||||
|
|
||||||
## OpenRC 0.47
|
## OpenRC 0.47
|
||||||
|
|
||||||
This release is primarily an internal cleanup release.
|
This release is primarily an internal cleanup release.
|
||||||
|
|||||||
@@ -183,10 +183,6 @@ Wait
|
|||||||
after starting and check that daemon is still running.
|
after starting and check that daemon is still running.
|
||||||
Useful for daemons that check configuration after forking or stopping race
|
Useful for daemons that check configuration after forking or stopping race
|
||||||
conditions where the pidfile is written out after forking.
|
conditions where the pidfile is written out after forking.
|
||||||
.It Fl 2 , -stderr Ar logfile
|
|
||||||
The same thing as
|
|
||||||
.Fl 1 , -stdout
|
|
||||||
but with the standard error output.
|
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
These options are only used for stopping daemons:
|
These options are only used for stopping daemons:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
project('OpenRC', 'c',
|
project('OpenRC', 'c',
|
||||||
version : '0.47',
|
version : '0.48',
|
||||||
license: 'BSD-2',
|
license: 'BSD-2',
|
||||||
default_options : [
|
default_options : [
|
||||||
'c_std=c99',
|
'c_std=c99',
|
||||||
@@ -176,7 +176,10 @@ cc_warning_flags_test = [
|
|||||||
'-Wsequence-point',
|
'-Wsequence-point',
|
||||||
'-Wshadow',
|
'-Wshadow',
|
||||||
'-Wwrite-strings',
|
'-Wwrite-strings',
|
||||||
|
'-Werror=implicit-int',
|
||||||
'-Werror=implicit-function-declaration',
|
'-Werror=implicit-function-declaration',
|
||||||
|
'-Werror=int-conversion',
|
||||||
|
'-Werror=incompatible-function-pointer-types',
|
||||||
]
|
]
|
||||||
cc_warning_flags = cc.get_supported_arguments(cc_warning_flags_test)
|
cc_warning_flags = cc.get_supported_arguments(cc_warning_flags_test)
|
||||||
cc_flags = [cc_debug_flags, cc_os_flags, cc_warning_flags]
|
cc_flags = [cc_debug_flags, cc_os_flags, cc_warning_flags]
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ int main(int argc, char **argv)
|
|||||||
if (strcmp(applet, "eend") == 0 ||
|
if (strcmp(applet, "eend") == 0 ||
|
||||||
strcmp(applet, "ewend") == 0 ||
|
strcmp(applet, "ewend") == 0 ||
|
||||||
strcmp(applet, "veend") == 0 ||
|
strcmp(applet, "veend") == 0 ||
|
||||||
strcmp(applet, "vweend") == 0 ||
|
strcmp(applet, "vewend") == 0 ||
|
||||||
strcmp(applet, "ewaitfile") == 0)
|
strcmp(applet, "ewaitfile") == 0)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <spawn.h>
|
||||||
|
|
||||||
/* Yay for linux and its non liking of POSIX functions.
|
/* Yay for linux and its non liking of POSIX functions.
|
||||||
Okay, we could use getfsent but the man page says use getmntent instead
|
Okay, we could use getfsent but the man page says use getmntent instead
|
||||||
@@ -63,6 +64,8 @@
|
|||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
const char *applet = NULL;
|
const char *applet = NULL;
|
||||||
const char *extraopts = NULL;
|
const char *extraopts = NULL;
|
||||||
const char getoptstring[] = "MRbmop:t:" getoptstring_COMMON;
|
const char getoptstring[] = "MRbmop:t:" getoptstring_COMMON;
|
||||||
@@ -112,7 +115,7 @@ do_mount(struct ENT *ent, bool remount)
|
|||||||
{
|
{
|
||||||
char *argv[10];
|
char *argv[10];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status, err;
|
||||||
|
|
||||||
argv[0] = UNCONST("mount");
|
argv[0] = UNCONST("mount");
|
||||||
argv[1] = UNCONST("-o");
|
argv[1] = UNCONST("-o");
|
||||||
@@ -137,23 +140,14 @@ do_mount(struct ENT *ent, bool remount)
|
|||||||
argv[8] = NULL;
|
argv[8] = NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
switch (pid = vfork()) {
|
err = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ);
|
||||||
case -1:
|
if (err)
|
||||||
eerrorx("%s: vfork: %s", applet, strerror(errno));
|
eerrorx("%s: posix_spawnp: %s", applet, strerror(err));
|
||||||
/* NOTREACHED */
|
while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
|
||||||
case 0:
|
|
||||||
execvp(argv[0], argv);
|
|
||||||
eerror("%s: execvp: %s", applet, strerror(errno));
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
/* NOTREACHED */
|
|
||||||
default:
|
|
||||||
waitpid(pid, &status, 0);
|
|
||||||
if (WIFEXITED(status))
|
if (WIFEXITED(status))
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OUTPUT_FILE (1 << 1)
|
#define OUTPUT_FILE (1 << 1)
|
||||||
|
|||||||
@@ -13,13 +13,8 @@
|
|||||||
#ifndef __EINFO_H__
|
#ifndef __EINFO_H__
|
||||||
#define __EINFO_H__
|
#define __EINFO_H__
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#define EINFO_PRINTF(a, b) __attribute__((__format__(__printf__, a, b)))
|
||||||
# define EINFO_PRINTF(a, b) __attribute__((__format__(__printf__, a, b)))
|
#define EINFO_XPRINTF(a, b) __attribute__((__noreturn__, __format__(__printf__, a, b)))
|
||||||
# define EINFO_XPRINTF(a, b) __attribute__((__noreturn__,__format__(__printf__, a, b)))
|
|
||||||
#else
|
|
||||||
# define EINFO_PRINTF(a, b)
|
|
||||||
# define EINFO_XPRINTF(a, b)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -74,22 +69,22 @@ void elog(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
|
|||||||
* The x suffix means function will exit() returning failure.
|
* The x suffix means function will exit() returning failure.
|
||||||
*/
|
*/
|
||||||
/*@{*/
|
/*@{*/
|
||||||
int einfon(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int einfon(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int ewarnn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int ewarnn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int eerrorn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int eerrorn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int einfo(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int einfo(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int ewarn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int ewarn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
void ewarnx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
|
void ewarnx(const char * EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
|
||||||
int eerror(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int eerror(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
void eerrorx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
|
void eerrorx(const char * EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2);
|
||||||
|
|
||||||
int einfovn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int einfovn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int ewarnvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int ewarnvn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int ebeginvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int ebeginvn(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int eendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
|
int eendvn(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
|
||||||
int ewendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
|
int ewendvn(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3);
|
||||||
int einfov(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int einfov(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
int ewarnv(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
int ewarnv(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2);
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/*! @ingroup ebegin
|
/*! @ingroup ebegin
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ rc_getline(char **line, size_t *len, FILE *fp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
rc_proc_getent(const char *ent _unused)
|
rc_proc_getent(const char *ent RC_UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@@ -287,6 +287,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
|
|||||||
overrides = rc_stringlist_new();
|
overrides = rc_stringlist_new();
|
||||||
|
|
||||||
/* A list of variables which may be overridden on the kernel command line */
|
/* A list of variables which may be overridden on the kernel command line */
|
||||||
|
rc_stringlist_add(overrides, "rc_interactive");
|
||||||
rc_stringlist_add(overrides, "rc_parallel");
|
rc_stringlist_add(overrides, "rc_parallel");
|
||||||
|
|
||||||
TAILQ_FOREACH(override, overrides, entries) {
|
TAILQ_FOREACH(override, overrides, entries) {
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ detect_prefix(const char *systype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
detect_container(const char *systype _unused)
|
detect_container(const char *systype RC_UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
if (systype) {
|
if (systype) {
|
||||||
@@ -313,7 +313,7 @@ detect_container(const char *systype _unused)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
detect_vm(const char *systype _unused)
|
detect_vm(const char *systype RC_UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef __NetBSD__
|
#ifdef __NetBSD__
|
||||||
if (systype) {
|
if (systype) {
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ static RC_STRINGLIST *deptypes_mwua; /* need+want+use+after deps for stopping */
|
|||||||
static void
|
static void
|
||||||
handle_signal(int sig)
|
handle_signal(int sig)
|
||||||
{
|
{
|
||||||
int serrno = errno;
|
int serrno = errno, status;
|
||||||
|
pid_t pid;
|
||||||
const char *signame = NULL;
|
const char *signame = NULL;
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
|
|
||||||
@@ -117,12 +118,13 @@ handle_signal(int sig)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
if (signal_pipe[1] > -1) {
|
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||||
if (write(signal_pipe[1], &sig, sizeof(sig)) == -1)
|
if (signal_pipe[1] > -1 && pid == service_pid) {
|
||||||
|
if (write(signal_pipe[1], &status, sizeof(status)) == -1)
|
||||||
eerror("%s: send: %s",
|
eerror("%s: send: %s",
|
||||||
service, strerror(errno));
|
service, strerror(errno));
|
||||||
} else
|
}
|
||||||
rc_waitpid(-1);
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGWINCH:
|
case SIGWINCH:
|
||||||
@@ -438,6 +440,7 @@ svc_exec(const char *arg1, const char *arg2)
|
|||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
eerror("%s: poll: %s",
|
eerror("%s: poll: %s",
|
||||||
service, strerror(errno));
|
service, strerror(errno));
|
||||||
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,10 +451,21 @@ svc_exec(const char *arg1, const char *arg2)
|
|||||||
write_prefix(buffer, bytes, &prefixed);
|
write_prefix(buffer, bytes, &prefixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only SIGCHLD signals come down this pipe */
|
/* signal_pipe receives service_pid's exit status */
|
||||||
if (fd[0].revents & (POLLIN | POLLHUP))
|
if (fd[0].revents & (POLLIN | POLLHUP)) {
|
||||||
|
if ((s = read(signal_pipe[0], &ret, sizeof(ret))) != sizeof(ret)) {
|
||||||
|
eerror("%s: receive failed: %s", service,
|
||||||
|
s < 0 ? strerror(errno) : "short read");
|
||||||
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ret = WEXITSTATUS(ret);
|
||||||
|
if (ret != 0 && errno == ECHILD)
|
||||||
|
/* killall5 -9 could cause this */
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@@ -473,11 +487,6 @@ svc_exec(const char *arg1, const char *arg2)
|
|||||||
master_tty = -1;
|
master_tty = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rc_waitpid(service_pid);
|
|
||||||
ret = WEXITSTATUS(ret);
|
|
||||||
if (ret != 0 && errno == ECHILD)
|
|
||||||
/* killall5 -9 could cause this */
|
|
||||||
ret = 0;
|
|
||||||
service_pid = 0;
|
service_pid = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -612,7 +621,7 @@ svc_start_check(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exclusive_fd == -1)
|
if (exclusive_fd == -1)
|
||||||
exclusive_fd = svc_lock(applet);
|
exclusive_fd = svc_lock(applet, !deps);
|
||||||
if (exclusive_fd == -1) {
|
if (exclusive_fd == -1) {
|
||||||
if (errno == EACCES)
|
if (errno == EACCES)
|
||||||
eerrorx("%s: superuser access required", applet);
|
eerrorx("%s: superuser access required", applet);
|
||||||
@@ -864,7 +873,7 @@ svc_stop_check(RC_SERVICE *state)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (exclusive_fd == -1)
|
if (exclusive_fd == -1)
|
||||||
exclusive_fd = svc_lock(applet);
|
exclusive_fd = svc_lock(applet, !deps);
|
||||||
if (exclusive_fd == -1) {
|
if (exclusive_fd == -1) {
|
||||||
if (errno == EACCES)
|
if (errno == EACCES)
|
||||||
eerrorx("%s: superuser access required", applet);
|
eerrorx("%s: superuser access required", applet);
|
||||||
@@ -1041,26 +1050,6 @@ svc_stop(void)
|
|||||||
static void
|
static void
|
||||||
svc_restart(void)
|
svc_restart(void)
|
||||||
{
|
{
|
||||||
/* This is hairy and a better way needs to be found I think!
|
|
||||||
* The issue is this - openvpn need net and dns. net can restart
|
|
||||||
* dns via resolvconf, so you could have openvpn trying to restart
|
|
||||||
* dnsmasq which in turn is waiting on net which in turn is waiting
|
|
||||||
* on dnsmasq.
|
|
||||||
* The work around is for resolvconf to restart its services with
|
|
||||||
* --nodeps which means just that.
|
|
||||||
* The downside is that there is a small window when our status is
|
|
||||||
* invalid.
|
|
||||||
* One workaround would be to introduce a new status,
|
|
||||||
* or status locking. */
|
|
||||||
if (!deps) {
|
|
||||||
RC_SERVICE state = rc_service_state(service);
|
|
||||||
if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE)
|
|
||||||
svc_exec("stop", "start");
|
|
||||||
else
|
|
||||||
svc_exec("start", NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) {
|
if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) {
|
||||||
get_started_services();
|
get_started_services();
|
||||||
svc_stop();
|
svc_stop();
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ static sigjmp_buf jbuf;
|
|||||||
/*
|
/*
|
||||||
* Alarm handler
|
* Alarm handler
|
||||||
*/
|
*/
|
||||||
/*ARGSUSED*/
|
RC_NORETURN static void handler(int arg RC_UNUSED)
|
||||||
_noreturn static void handler(int arg _unused)
|
|
||||||
{
|
{
|
||||||
siglongjmp(jbuf, 1);
|
siglongjmp(jbuf, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ static void sleep_no_interrupt(int seconds)
|
|||||||
duration = remaining;
|
duration = remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn static void stop_shutdown(int sig)
|
RC_NORETURN static void stop_shutdown(int sig)
|
||||||
{
|
{
|
||||||
(void) sig;
|
(void) sig;
|
||||||
unlink(nologin_file);
|
unlink(nologin_file);
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ static RC_HOOK hook_out;
|
|||||||
struct termios *termios_orig = NULL;
|
struct termios *termios_orig = NULL;
|
||||||
|
|
||||||
RC_PIDLIST service_pids;
|
RC_PIDLIST service_pids;
|
||||||
|
RC_PIDLIST free_these_pids;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clean_failed(void)
|
clean_failed(void)
|
||||||
@@ -116,8 +117,7 @@ clean_failed(void)
|
|||||||
static void
|
static void
|
||||||
cleanup(void)
|
cleanup(void)
|
||||||
{
|
{
|
||||||
RC_PID *p1 = LIST_FIRST(&service_pids);
|
RC_PID *p, *tmp;
|
||||||
RC_PID *p2;
|
|
||||||
|
|
||||||
if (!rc_in_logger && !rc_in_plugin &&
|
if (!rc_in_logger && !rc_in_plugin &&
|
||||||
applet && (strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0))
|
applet && (strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0))
|
||||||
@@ -139,10 +139,13 @@ cleanup(void)
|
|||||||
rc_logger_close();
|
rc_logger_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (p1) {
|
LIST_FOREACH_SAFE(p, &service_pids, entries, tmp) {
|
||||||
p2 = LIST_NEXT(p1, entries);
|
LIST_REMOVE(p, entries);
|
||||||
free(p1);
|
free(p);
|
||||||
p1 = p2;
|
}
|
||||||
|
LIST_FOREACH_SAFE(p, &free_these_pids, entries, tmp) {
|
||||||
|
LIST_REMOVE(p, entries);
|
||||||
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_stringlist_free(main_hotplugged_services);
|
rc_stringlist_free(main_hotplugged_services);
|
||||||
@@ -344,22 +347,46 @@ static char *get_krunlevel(void)
|
|||||||
static void
|
static void
|
||||||
add_pid(pid_t pid)
|
add_pid(pid_t pid)
|
||||||
{
|
{
|
||||||
|
sigset_t sset, old;
|
||||||
RC_PID *p = xmalloc(sizeof(*p));
|
RC_PID *p = xmalloc(sizeof(*p));
|
||||||
p->pid = pid;
|
p->pid = pid;
|
||||||
|
|
||||||
|
/* this list will be accessed inside the SIGCHLD signal handler.
|
||||||
|
* so we need to ensure that the SIGCHLD handler doesn't get invoked
|
||||||
|
* while the list is at an inconsistent state.
|
||||||
|
*/
|
||||||
|
sigemptyset(&sset);
|
||||||
|
sigaddset(&sset, SIGCHLD);
|
||||||
|
sigprocmask(SIG_SETMASK, &sset, &old);
|
||||||
LIST_INSERT_HEAD(&service_pids, p, entries);
|
LIST_INSERT_HEAD(&service_pids, p, entries);
|
||||||
|
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_pid(pid_t pid)
|
remove_pid(pid_t pid, bool inside_signal)
|
||||||
{
|
{
|
||||||
RC_PID *p;
|
sigset_t sset, old;
|
||||||
|
RC_PID *p, *tmp;
|
||||||
|
|
||||||
LIST_FOREACH(p, &service_pids, entries)
|
/* same rationale for blocking SIGCHLD as add_pid() */
|
||||||
|
sigemptyset(&sset);
|
||||||
|
sigaddset(&sset, SIGCHLD);
|
||||||
|
sigprocmask(SIG_SETMASK, &sset, &old);
|
||||||
|
LIST_FOREACH(p, &service_pids, entries) {
|
||||||
if (p->pid == pid) {
|
if (p->pid == pid) {
|
||||||
LIST_REMOVE(p, entries);
|
LIST_REMOVE(p, entries);
|
||||||
free(p);
|
LIST_INSERT_HEAD(&free_these_pids, p, entries);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/* only call free if we're not inside a signal handler */
|
||||||
|
if (!inside_signal) {
|
||||||
|
LIST_FOREACH_SAFE(p, &free_these_pids, entries, tmp) {
|
||||||
|
LIST_REMOVE(p, entries);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -397,7 +424,7 @@ handle_signal(int sig)
|
|||||||
|
|
||||||
/* Remove that pid from our list */
|
/* Remove that pid from our list */
|
||||||
if (pid > 0)
|
if (pid > 0)
|
||||||
remove_pid(pid);
|
remove_pid(pid, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGWINCH:
|
case SIGWINCH:
|
||||||
@@ -606,7 +633,7 @@ stop:
|
|||||||
add_pid(pid);
|
add_pid(pid);
|
||||||
if (!parallel) {
|
if (!parallel) {
|
||||||
rc_waitpid(pid);
|
rc_waitpid(pid);
|
||||||
remove_pid(pid);
|
remove_pid(pid, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -672,7 +699,7 @@ do_start_services(const RC_STRINGLIST *start_services, bool parallel)
|
|||||||
add_pid(pid);
|
add_pid(pid);
|
||||||
if (!parallel) {
|
if (!parallel) {
|
||||||
rc_waitpid(pid);
|
rc_waitpid(pid);
|
||||||
remove_pid(pid);
|
remove_pid(pid, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -690,7 +717,7 @@ do_start_services(const RC_STRINGLIST *start_services, bool parallel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RC_DEBUG
|
#ifdef RC_DEBUG
|
||||||
_noreturn static void
|
RC_NORETURN static void
|
||||||
handle_bad_signal(int sig)
|
handle_bad_signal(int sig)
|
||||||
{
|
{
|
||||||
char pid[10];
|
char pid[10];
|
||||||
@@ -745,6 +772,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
applet = basename_c(argv[0]);
|
applet = basename_c(argv[0]);
|
||||||
LIST_INIT(&service_pids);
|
LIST_INIT(&service_pids);
|
||||||
|
LIST_INIT(&free_these_pids);
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
if (!applet)
|
if (!applet)
|
||||||
eerrorx("arguments required");
|
eerrorx("arguments required");
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ void set_quiet_options(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn void show_version(void)
|
RC_NORETURN void show_version(void)
|
||||||
{
|
{
|
||||||
const char *systype = NULL;
|
const char *systype = NULL;
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ _noreturn void show_version(void)
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn void usage(int exit_status)
|
RC_NORETURN void usage(int exit_status)
|
||||||
{
|
{
|
||||||
const char * const has_arg[] = { "", "<arg>", "[arg]" };
|
const char * const has_arg[] = { "", "<arg>", "[arg]" };
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -28,22 +29,11 @@
|
|||||||
|
|
||||||
#define ERRX fprintf (stderr, "out of memory\n"); exit (1)
|
#define ERRX fprintf (stderr, "out of memory\n"); exit (1)
|
||||||
|
|
||||||
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
|
||||||
|
|
||||||
#ifdef lint
|
#define RC_UNUSED __attribute__((__unused__))
|
||||||
# define _unused
|
#define RC_NORETURN __attribute__((__noreturn__))
|
||||||
#endif
|
#define RC_PRINTF(a, b) __attribute__((__format__(__printf__, a, b)))
|
||||||
#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
|
|
||||||
# define _dead __attribute__((__noreturn__))
|
|
||||||
# define _noreturn __attribute__ ((__noreturn__))
|
|
||||||
# define _unused __attribute__((__unused__))
|
|
||||||
# define _xasprintf(a, b) __attribute__((__format__(__printf__, a, b)))
|
|
||||||
#else
|
|
||||||
# define _dead
|
|
||||||
# define _noreturn
|
|
||||||
# define _unused
|
|
||||||
# define _xasprintf(a, b)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
|
||||||
@@ -65,7 +55,7 @@
|
|||||||
} while (/* CONSTCOND */ 0)
|
} while (/* CONSTCOND */ 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_unused static void *xmalloc (size_t size)
|
RC_UNUSED static void *xmalloc (size_t size)
|
||||||
{
|
{
|
||||||
void *value = malloc(size);
|
void *value = malloc(size);
|
||||||
|
|
||||||
@@ -76,7 +66,7 @@ _unused static void *xmalloc (size_t size)
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
_unused static void *xrealloc(void *ptr, size_t size)
|
RC_UNUSED static void *xrealloc(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
void *value = realloc(ptr, size);
|
void *value = realloc(ptr, size);
|
||||||
|
|
||||||
@@ -87,7 +77,7 @@ _unused static void *xrealloc(void *ptr, size_t size)
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
_unused static char *xstrdup(const char *str)
|
RC_UNUSED static char *xstrdup(const char *str)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
@@ -109,7 +99,7 @@ _unused static char *xstrdup(const char *str)
|
|||||||
* basename_c never modifies the argument. As such, if there is a trailing
|
* basename_c never modifies the argument. As such, if there is a trailing
|
||||||
* slash then an empty string is returned.
|
* slash then an empty string is returned.
|
||||||
*/
|
*/
|
||||||
_unused static const char *basename_c(const char *path)
|
RC_UNUSED static const char *basename_c(const char *path)
|
||||||
{
|
{
|
||||||
const char *slash = strrchr(path, '/');
|
const char *slash = strrchr(path, '/');
|
||||||
|
|
||||||
@@ -118,14 +108,14 @@ _unused static const char *basename_c(const char *path)
|
|||||||
return (path);
|
return (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
_unused static bool exists(const char *pathname)
|
RC_UNUSED static bool exists(const char *pathname)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
return (stat(pathname, &buf) == 0);
|
return (stat(pathname, &buf) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_unused static bool existss(const char *pathname)
|
RC_UNUSED static bool existss(const char *pathname)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
@@ -140,7 +130,7 @@ _unused static bool existss(const char *pathname)
|
|||||||
* functions to handle memory allocation.
|
* functions to handle memory allocation.
|
||||||
* this function was originally written by Mike Frysinger.
|
* this function was originally written by Mike Frysinger.
|
||||||
*/
|
*/
|
||||||
_unused _xasprintf(2,3) static int xasprintf(char **strp, const char *fmt, ...)
|
RC_UNUSED RC_PRINTF(2,3) static int xasprintf(char **strp, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int len;
|
int len;
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ signal_setup_restart(int sig, void (*handler)(int))
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
svc_lock(const char *applet)
|
svc_lock(const char *applet, bool ignore_lock_failure)
|
||||||
{
|
{
|
||||||
char *file = NULL;
|
char *file = NULL;
|
||||||
int fd;
|
int fd;
|
||||||
@@ -245,6 +245,14 @@ svc_lock(const char *applet)
|
|||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
|
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
|
||||||
|
if (ignore_lock_failure) {
|
||||||
|
/* Two services with a need b, and b's start()
|
||||||
|
* calling restart --no-deps on a would cause
|
||||||
|
* harmless errors: just ignore them.
|
||||||
|
* See https://github.com/OpenRC/openrc/issues/224
|
||||||
|
*/
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
eerror("Call to flock failed: %s", strerror(errno));
|
eerror("Call to flock failed: %s", strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -274,7 +282,7 @@ exec_service(const char *service, const char *arg)
|
|||||||
sigset_t old;
|
sigset_t old;
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
fd = svc_lock(basename_c(service));
|
fd = svc_lock(basename_c(service), false);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ void env_filter(void);
|
|||||||
void env_config(void);
|
void env_config(void);
|
||||||
int signal_setup(int sig, void (*handler)(int));
|
int signal_setup(int sig, void (*handler)(int));
|
||||||
int signal_setup_restart(int sig, void (*handler)(int));
|
int signal_setup_restart(int sig, void (*handler)(int));
|
||||||
int svc_lock(const char *);
|
int svc_lock(const char *, bool);
|
||||||
int svc_unlock(const char *, int);
|
int svc_unlock(const char *, int);
|
||||||
pid_t exec_service(const char *, const char *);
|
pid_t exec_service(const char *, const char *);
|
||||||
|
|
||||||
|
|||||||
@@ -179,9 +179,9 @@ extern char **environ;
|
|||||||
# define SYS_ioprio_set __NR_ioprio_set
|
# define SYS_ioprio_set __NR_ioprio_set
|
||||||
#endif
|
#endif
|
||||||
#if !defined(__DragonFly__)
|
#if !defined(__DragonFly__)
|
||||||
static inline int ioprio_set(int which _unused,
|
static inline int ioprio_set(int which RC_UNUSED,
|
||||||
int who _unused,
|
int who RC_UNUSED,
|
||||||
int ioprio _unused)
|
int ioprio RC_UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef SYS_ioprio_set
|
#ifdef SYS_ioprio_set
|
||||||
return syscall(SYS_ioprio_set, which, who, ioprio);
|
return syscall(SYS_ioprio_set, which, who, ioprio);
|
||||||
|
|||||||
@@ -192,8 +192,8 @@ extern char **environ;
|
|||||||
# define SYS_ioprio_set __NR_ioprio_set
|
# define SYS_ioprio_set __NR_ioprio_set
|
||||||
#endif
|
#endif
|
||||||
#if !defined(__DragonFly__)
|
#if !defined(__DragonFly__)
|
||||||
static inline int ioprio_set(int which _unused, int who _unused,
|
static inline int ioprio_set(int which RC_UNUSED, int who RC_UNUSED,
|
||||||
int ioprio _unused)
|
int ioprio RC_UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef SYS_ioprio_set
|
#ifdef SYS_ioprio_set
|
||||||
return syscall(SYS_ioprio_set, which, who, ioprio);
|
return syscall(SYS_ioprio_set, which, who, ioprio);
|
||||||
@@ -208,7 +208,7 @@ static void cleanup(void)
|
|||||||
free(changeuser);
|
free(changeuser);
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn static void re_exec_supervisor(void)
|
RC_NORETURN static void re_exec_supervisor(void)
|
||||||
{
|
{
|
||||||
syslog(LOG_WARNING, "Re-executing for %s", svcname);
|
syslog(LOG_WARNING, "Re-executing for %s", svcname);
|
||||||
execlp("supervise-daemon", "supervise-daemon", svcname, "--reexec",
|
execlp("supervise-daemon", "supervise-daemon", svcname, "--reexec",
|
||||||
@@ -354,7 +354,7 @@ static pid_t exec_command(const char *cmd)
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn static void child_process(char *exec, char **argv)
|
RC_NORETURN static void child_process(char *exec, char **argv)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *env_list;
|
RC_STRINGLIST *env_list;
|
||||||
RC_STRING *env;
|
RC_STRING *env;
|
||||||
@@ -587,7 +587,7 @@ _noreturn static void child_process(char *exec, char **argv)
|
|||||||
eerrorx("%s: failed to exec `%s': %s", applet, exec,strerror(errno));
|
eerrorx("%s: failed to exec `%s': %s", applet, exec,strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
_noreturn static void supervisor(char *exec, char **argv)
|
RC_NORETURN static void supervisor(char *exec, char **argv)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
|
|||||||
Reference in New Issue
Block a user