#include "control.h"
#include "service.h"
+namespace {
+ constexpr auto OUT_EVENTS = dasynq::OUT_EVENTS;
+ constexpr auto IN_EVENTS = dasynq::IN_EVENTS;
+}
+
bool control_conn_t::process_packet()
{
using std::string;
// Control connection for dinit
-using namespace dasynq;
-using eventloop_t = event_loop<null_mutex>;
+using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
class control_conn_t;
class control_conn_watcher;
// forward-declaration of callback:
-static rearm control_conn_cb(eventloop_t *loop, control_conn_watcher *watcher, int revents);
+static dasynq::rearm control_conn_cb(eventloop_t *loop, control_conn_watcher *watcher, int revents);
// Pointer to the control connection that is listening for rollback completion
extern control_conn_t * rollback_handler_conn;
class control_conn_watcher : public eventloop_t::bidi_fd_watcher_impl<control_conn_watcher>
{
+ using rearm = dasynq::rearm;
inline rearm receive_event(eventloop_t &loop, int fd, int flags) noexcept;
eventloop_t * event_loop;
rearm read_ready(eventloop_t &loop, int fd) noexcept
{
- return receive_event(loop, fd, IN_EVENTS);
+ return receive_event(loop, fd, dasynq::IN_EVENTS);
}
rearm write_ready(eventloop_t &loop, int fd) noexcept
{
- return receive_event(loop, fd, OUT_EVENTS);
+ return receive_event(loop, fd, dasynq::OUT_EVENTS);
}
void set_watches(int flags)
}
};
-inline rearm control_conn_watcher::receive_event(eventloop_t &loop, int fd, int flags) noexcept
+inline dasynq::rearm control_conn_watcher::receive_event(eventloop_t &loop, int fd, int flags) noexcept
{
return control_conn_cb(&loop, this, flags);
}
class control_conn_t : private service_listener
{
+ using rearm = dasynq::rearm;
friend rearm control_conn_cb(eventloop_t *loop, control_conn_watcher *watcher, int revents);
control_conn_watcher iob;
{
bad_conn_close = true;
oom_close = true;
- iob.set_watches(OUT_EVENTS);
+ iob.set_watches(dasynq::OUT_EVENTS);
}
// Process service event broadcast.
control_conn_t(eventloop_t &loop, service_set * services_p, int fd)
: iob(loop), loop(loop), services(services_p), chklen(0)
{
- iob.add_watch(loop, fd, IN_EVENTS);
+ iob.add_watch(loop, fd, dasynq::IN_EVENTS);
active_control_conns++;
}
};
-static rearm control_conn_cb(eventloop_t * loop, control_conn_watcher * watcher, int revents)
+static dasynq::rearm control_conn_cb(eventloop_t * loop, control_conn_watcher * watcher, int revents)
{
// Get the address of the containing control_connt_t object:
_Pragma ("GCC diagnostic push")
control_conn_t *conn = reinterpret_cast<control_conn_t *>(cc_addr);
_Pragma ("GCC diagnostic pop")
- if (revents & IN_EVENTS) {
+ if (revents & dasynq::IN_EVENTS) {
if (conn->data_ready()) {
delete conn;
- return rearm::REMOVED;
+ return dasynq::rearm::REMOVED;
}
}
- if (revents & OUT_EVENTS) {
+ if (revents & dasynq::OUT_EVENTS) {
if (conn->send_data()) {
delete conn;
- return rearm::REMOVED;
+ return dasynq::rearm::REMOVED;
}
}
- return rearm::NOOP;
+ return dasynq::rearm::NOOP;
}
#endif
#include "dinit-log.h"
#include "cpbuffer.h"
-extern eventloop_t eventLoop;
+extern eventloop_t event_loop;
static bool log_current_line[2]; // Whether the current line is being logged (for console, main log)
loglevel_t log_level[2] = { loglevel_t::WARN, loglevel_t::WARN };
static service_set *services = nullptr; // Reference to service set
+using rearm = dasynq::rearm;
+
namespace {
class BufferedLogStream : public eventloop_t::fd_watcher_impl<BufferedLogStream>
{
bool was_first = current_index == 0;
current_index = log_buffer.get_length();
if (was_first && ! release) {
- set_enabled(eventLoop, true);
+ set_enabled(event_loop, true);
}
}
// Try to flush any messages that are currently buffered. (Console is non-blocking
// so it will fail gracefully).
- if (fd_event(eventLoop, fd, OUT_EVENTS) == rearm::DISARM) {
+ if (fd_event(event_loop, fd, dasynq::OUT_EVENTS) == rearm::DISARM) {
// Console has already been released at this point.
- set_enabled(eventLoop, false);
+ set_enabled(event_loop, false);
}
// fd_event didn't want to disarm, so must be partway through a message; will
// release when it's finished.
void init_log(service_set *sset)
{
services = sset;
- log_stream[DLOG_CONS].add_watch(eventLoop, STDOUT_FILENO, OUT_EVENTS, false);
+ log_stream[DLOG_CONS].add_watch(event_loop, STDOUT_FILENO, dasynq::OUT_EVENTS, false);
enable_console_log(true);
}
void setup_main_log(int fd)
{
log_stream[DLOG_MAIN].init(fd);
- log_stream[DLOG_MAIN].add_watch(eventLoop, fd, OUT_EVENTS);
+ log_stream[DLOG_MAIN].add_watch(event_loop, fd, dasynq::OUT_EVENTS);
}
bool is_log_flushed() noexcept
fcntl(1, F_SETFL, flags | O_NONBLOCK);
// Activate watcher:
log_stream[DLOG_CONS].init(STDOUT_FILENO);
- log_stream[DLOG_CONS].set_enabled(eventLoop, true);
+ log_stream[DLOG_CONS].set_enabled(event_loop, true);
}
else if (! enable && log_to_console) {
log_stream[DLOG_CONS].flushForRelease();
* services even if the halt/reboot commands are unavailable for some reason.
*/
-using namespace dasynq;
-using eventloop_t = event_loop<null_mutex>;
+using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
-eventloop_t eventLoop;
+eventloop_t event_loop;
static void sigint_reboot_cb(eventloop_t &eloop) noexcept;
static void sigquit_cb(eventloop_t &eloop) noexcept;
namespace {
class callback_signal_handler : public eventloop_t::signal_watcher_impl<callback_signal_handler>
{
+ using rearm = dasynq::rearm;
+
public:
typedef void (*cb_func_t)(eventloop_t &);
class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
{
+ using rearm = dasynq::rearm;
+
public:
rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
{
sigint_watcher.setCbFunc(sigterm_cb);
}
- sigint_watcher.add_watch(eventLoop, SIGINT);
- sigterm_watcher.add_watch(eventLoop, SIGTERM);
+ sigint_watcher.add_watch(event_loop, SIGINT);
+ sigterm_watcher.add_watch(event_loop, SIGTERM);
if (am_system_init) {
// PID 1: SIGQUIT exec's shutdown
- sigquit_watcher.add_watch(eventLoop, SIGQUIT);
+ sigquit_watcher.add_watch(event_loop, SIGQUIT);
// As a user process, we instead just let SIGQUIT perform the default action.
}
// Process events until all services have terminated.
while (services->count_active_services() != 0) {
- eventLoop.run();
+ event_loop.run();
}
shutdown_type_t shutdown_type = services->getShutdownType();
}
while (! is_log_flushed()) {
- eventLoop.run();
+ event_loop.run();
}
close_control_socket();
// PID 1 must not actually exit, although we should never reach this point:
while (true) {
- eventLoop.run();
+ event_loop.run();
}
}
else if (shutdown_type == shutdown_type_t::REBOOT) {
}
try {
- control_socket_io.add_watch(eventLoop, sockfd, IN_EVENTS);
+ control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
control_socket_open = true;
}
catch (std::exception &e)
{
if (control_socket_open) {
int fd = control_socket_io.get_watched_fd();
- control_socket_io.deregister(eventLoop);
+ control_socket_io.deregister(event_loop);
close(fd);
// Unlink the socket:
// from dinit.cc:
void open_control_socket(bool report_ro_failure = true) noexcept;
void setup_external_log() noexcept;
-extern eventloop_t eventLoop;
+extern eventloop_t event_loop;
+
+using clock_type = dasynq::clock_type;
+using rearm = dasynq::rearm;
+using time_val = dasynq::time_val;
// Find the requested service by name
static service_record * find_service(const std::list<service_record *> & records,
if (sr->waiting_for_execstat) {
// We still don't have an exec() status from the forked child, wait for that
// before doing any further processing.
- return rearm::NOOP; // hold watch reservation
+ return dasynq::rearm::NOOP; // hold watch reservation
}
// Must stop watch now since handle_exit_status might result in re-launch:
}
sr->handle_exit_status(status);
- return rearm::NOOP;
+ return dasynq::rearm::NOOP;
}
bool service_record::do_auto_restart() noexcept
if (r > 0) {
// We read an errno code; exec() failed, and the service startup failed.
if (sr->pid != -1) {
- sr->child_listener.deregister(eventLoop, sr->pid);
+ sr->child_listener.deregister(event_loop, sr->pid);
sr->reserved_child_watch = false;
if (sr->stop_timer_armed) {
sr->restart_timer.stop_timer(loop);
}
else if (wait_r == 0) {
// We can track the child
- child_listener.add_reserved(eventLoop, pid, DEFAULT_PRIORITY - 10);
+ child_listener.add_reserved(event_loop, pid, dasynq::DEFAULT_PRIORITY - 10);
tracking_child = true;
reserved_child_watch = true;
return pid_result_t::OK;
return true;
}
else {
- eventLoop.get_time(restart_interval_time, clock_type::MONOTONIC);
+ event_loop.get_time(restart_interval_time, clock_type::MONOTONIC);
restart_interval_count = 0;
if (start_ps_process(exec_arg_parts, onstart_flags.starts_on_console)) {
if (start_timeout != time_val(0,0)) {
- restart_timer.arm_timer_rel(eventLoop, start_timeout);
+ restart_timer.arm_timer_rel(event_loop, start_timeout);
stop_timer_armed = true;
}
else if (stop_timer_armed) {
- restart_timer.stop_timer(eventLoop);
+ restart_timer.stop_timer(event_loop);
stop_timer_armed = false;
}
return true;
// exec closes the pipe, and the parent sees EOF. If the exec is unsuccessful, the errno
// is written to the pipe, and the parent can read it.
- eventLoop.get_time(last_start_time, clock_type::MONOTONIC);
+ event_loop.get_time(last_start_time, clock_type::MONOTONIC);
int pipefd[2];
- if (pipe2(pipefd, O_CLOEXEC)) {
+ if (dasynq::pipe2(pipefd, O_CLOEXEC)) {
log(loglevel_t::ERROR, get_name(), ": can't create status check pipe: ", strerror(errno));
return false;
}
fcntl(control_socket[0], F_SETFD, fdflags | FD_CLOEXEC);
try {
- control_conn = new control_conn_t(eventLoop, services, control_socket[0]);
+ control_conn = new control_conn_t(event_loop, services, control_socket[0]);
}
catch (std::exception &exc) {
log(loglevel_t::ERROR, get_name(), ": can't launch process; out of memory");
pid_t forkpid;
try {
- child_status_listener.add_watch(eventLoop, pipefd[0], IN_EVENTS);
+ child_status_listener.add_watch(event_loop, pipefd[0], dasynq::IN_EVENTS);
child_status_registered = true;
// We specify a high priority (i.e. low priority value) so that process termination is
// handled early. This means we have always recorded that the process is terminated by the
// time that we handle events that might otherwise cause us to signal the process, so we
// avoid sending a signal to an invalid (and possibly recycled) process ID.
- forkpid = child_listener.fork(eventLoop, reserved_child_watch, DEFAULT_PRIORITY - 10);
+ forkpid = child_listener.fork(event_loop, reserved_child_watch, dasynq::DEFAULT_PRIORITY - 10);
reserved_child_watch = true;
}
catch (std::exception &e) {
out_cs_h:
if (child_status_registered) {
- child_status_listener.deregister(eventLoop);
+ child_status_listener.deregister(event_loop);
}
if (onstart_flags.pass_cs_fd) {
stopped();
}
else if (stop_timeout != time_val(0,0)) {
- restart_timer.arm_timer_rel(eventLoop, stop_timeout);
+ restart_timer.arm_timer_rel(event_loop, stop_timeout);
stop_timer_armed = true;
}
}
stopped();
}
else if (stop_timeout != time_val(0,0)) {
- restart_timer.arm_timer_rel(eventLoop, stop_timeout);
+ restart_timer.arm_timer_rel(event_loop, stop_timeout);
stop_timer_armed = true;
}
}
else {
// successfully started stop script: start kill timer:
if (stop_timeout != time_val(0,0)) {
- restart_timer.arm_timer_rel(eventLoop, stop_timeout);
+ restart_timer.arm_timer_rel(event_loop, stop_timeout);
stop_timer_armed = true;
}
}
restart_interval_count = 0;
restart_interval_time = {0, 0};
restart_timer.service = this;
- restart_timer.add_timer(eventLoop);
+ restart_timer.add_timer(event_loop);
// By default, allow a maximum of 3 restarts within 10.0 seconds:
restart_interval.seconds() = 10;
using time_val = dasynq::time_val;
time_val current_time;
- eventLoop.get_time(current_time, clock_type::MONOTONIC);
+ event_loop.get_time(current_time, clock_type::MONOTONIC);
if (max_restart_interval_count != 0) {
// Check whether we're still in the most recent restart check interval:
}
else {
time_val timeout = restart_delay - tdiff;
- restart_timer.arm_timer_rel(eventLoop, timeout);
+ restart_timer.arm_timer_rel(event_loop, timeout);
waiting_restart_timer = true;
}
return true;
bool base_process_service::interrupt_start() noexcept
{
if (waiting_restart_timer) {
- restart_timer.stop_timer(eventLoop);
+ restart_timer.stop_timer(event_loop);
waiting_restart_timer = false;
return service_record::interrupt_start();
}
log(loglevel_t::WARN, "Interrupting start of service ", get_name(), " with pid ", pid, " (with SIGINT).");
kill_pg(SIGINT);
if (stop_timeout != time_val(0,0)) {
- restart_timer.arm_timer(eventLoop, stop_timeout);
+ restart_timer.arm_timer(event_loop, stop_timeout);
stop_timer_armed = true;
}
else if (stop_timer_armed) {
- restart_timer.stop_timer(eventLoop);
+ restart_timer.stop_timer(event_loop);
stop_timer_armed = false;
}
set_state(service_state_t::STOPPING);
{
public:
base_process_service * service;
- rearm status_change(eventloop_t &eloop, pid_t child, int status) noexcept;
+ dasynq::rearm status_change(eventloop_t &eloop, pid_t child, int status) noexcept;
service_child_watcher(base_process_service * sr) noexcept : service(sr) { }
};
{
public:
base_process_service * service;
- rearm fd_event(eventloop_t &eloop, int fd, int flags) noexcept;
+ dasynq::rearm fd_event(eventloop_t &eloop, int fd, int flags) noexcept;
exec_status_pipe_watcher(base_process_service * sr) noexcept : service(sr) { }
};
{
protected:
using string = std::string;
+ using time_val = dasynq::time_val;
private:
string service_name;
{
}
- rearm timer_expiry(eventloop_t &, int expiry_count);
+ dasynq::rearm timer_expiry(eventloop_t &, int expiry_count);
};
class base_process_service : public service_record