#ifndef DINIT_LL_INCLUDED
#define DINIT_LL_INCLUDED 1
-// Simple doubly-linked list implementation, where the contained element includes the
-// list node. This allows a single item to be a member of several different kinds of
-// list, without requiring dynamicall allocation of nodes.
+// Simple single- and doubly-linked list implementation, where the contained element includes the
+// list node. This allows a single item to be a member of several different kinds of list, without
+// requiring dynamic allocation of nodes.
template <typename T>
struct lld_node
}
return r;
}
+
+ void unlink(T *record) noexcept
+ {
+ auto &node = E(record);
+ if (first == record) {
+ first = node.next;
+ if (first == record) {
+ // unlinking the only node in the list:
+ first = nullptr;
+ }
+ }
+ E(node.next).prev = node.prev;
+ E(node.prev).next = node.next;
+ node.next = nullptr;
+ node.prev = nullptr;
+ }
};
template <typename T, lls_node<T> &(*E)(T *)>
if (release) {
int flags = fcntl(1, F_GETFL, 0);
fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
- service_set->pullConsoleQueue();
+ service_set->pull_console_queue();
}
}
// We must have had desired_state == STARTED.
notifyListeners(ServiceEvent::STARTCANCELLED);
+ interrupt_start();
+
// Reaching this point, we are starting interruptibly - so we
// stop now (by falling through to below).
}
void ServiceRecord::release_console() noexcept
{
- service_set->pullConsoleQueue();
+ service_set->pull_console_queue();
+}
+
+void ServiceRecord::interrupt_start() noexcept
+{
+ service_set->unqueue_console(this);
}
void ServiceSet::service_active(ServiceRecord *sr) noexcept
restart_timer.stop_timer(eventLoop);
waiting_restart_timer = false;
}
+ ServiceRecord::interrupt_start();
}
dasynq::rearm process_restart_timer::timer_expiry(EventLoop_t &, int expiry_count)
return waiting_for_deps;
}
- virtual void interrupt_start() noexcept
- {
- // overridden in subclasses
- }
+ virtual void interrupt_start() noexcept;
// Whether a STOPPING service can immediately transition to STARTED.
bool can_interrupt_stop() noexcept
public:
ServiceRecord(ServiceSet *set, string name)
- : service_state(ServiceState::STOPPED), desired_state(ServiceState::STOPPED), auto_restart(false),
+ : service_state(ServiceState::STOPPED), desired_state(ServiceState::STOPPED),
+ auto_restart(false), smooth_recovery(false),
pinned_stopped(false), pinned_started(false), waiting_for_deps(false),
waiting_for_execstat(false), start_explicit(false),
prop_require(false), prop_release(false), prop_failure(false),
}
// Retrieve the current console queue head and remove it from the queue
- ServiceRecord * pullConsoleQueue() noexcept
+ ServiceRecord * pull_console_queue() noexcept
{
return console_queue.pop_front();
}
+ void unqueue_console(ServiceRecord * service) noexcept
+ {
+ if (console_queue.is_queued(service)) {
+ console_queue.unlink(service);
+ }
+ }
+
// Notification from service that it is active (state != STOPPED)
// Only to be called on the transition from inactive to active.
void service_active(ServiceRecord *) noexcept;