sset.remove_service(&p);
}
+// Unexpected termination
+void test_proc_term_restart()
+{
+ using namespace std;
+
+ service_set sset;
+
+ string command = "test-command";
+ list<pair<unsigned,unsigned>> command_offsets;
+ command_offsets.emplace_back(0, command.length());
+ std::list<prelim_dep> depends;
+
+ process_service p {&sset, "testproc", std::move(command), command_offsets, depends};
+ init_service_defaults(p);
+ p.set_auto_restart(true);
+ sset.add_service(&p);
+
+ p.start(true);
+ sset.process_queues();
+
+ base_process_service_test::exec_succeeded(&p);
+ sset.process_queues();
+
+ assert(p.get_state() == service_state_t::STARTED);
+ assert(event_loop.active_timers.size() == 0);
+
+ base_process_service_test::handle_exit(&p, 0);
+ sset.process_queues();
+
+ // Starting, restart timer should be armed:
+ assert(p.get_state() == service_state_t::STARTING);
+ assert(event_loop.active_timers.size() == 1);
+
+ event_loop.advance_time(time_val(0, 200000000));
+ assert(event_loop.active_timers.size() == 0);
+
+ sset.process_queues();
+ base_process_service_test::exec_succeeded(&p);
+ sset.process_queues();
+
+ assert(p.get_state() == service_state_t::STARTED);
+ assert(event_loop.active_timers.size() == 0);
+
+ sset.remove_service(&p);
+}
+
// Termination via stop request
void test_term_via_stop()
{
RUN_TEST(test_proc_service_start, " ");
RUN_TEST(test_proc_notify_start, " ");
RUN_TEST(test_proc_unexpected_term, " ");
+ RUN_TEST(test_proc_term_restart, " ");
RUN_TEST(test_term_via_stop, " ");
RUN_TEST(test_term_via_stop2, " ");
RUN_TEST(test_proc_start_timeout, " ");
#include <unordered_set>
#include <map>
#include <string>
+#include <cassert>
#include "dasynq.h"
class eventloop_t
{
+ time_val current_time {0, 0};
+
public:
void get_time(time_val &tv, dasynq::clock_type clock) noexcept
{
- tv = {0, 0};
+ tv = current_time;
+ }
+
+ void advance_time(time_val amount)
+ {
+ current_time += amount;
+ for (timer * t : active_timers) {
+ if (t->expiry_time >= current_time) {
+ t->stop_timer(*this);
+ rearm r = t->expired(*this, 1);
+ assert(r == rearm::NOOP); // others not handled
+ }
+ }
}
class child_proc_watcher
class timer
{
+ friend class eventloop_t;
+
+ private:
+ time_val expiry_time;
+
+ protected:
+ virtual rearm expired(eventloop_t &loop, int expiry_count)
+ {
+ return rearm::NOOP;
+ }
+
public:
void add_timer(eventloop_t &loop)
{
void arm_timer_rel(eventloop_t &loop, time_val timeout) noexcept
{
+ expiry_time = loop.current_time + timeout;
loop.active_timers.insert(this);
}
template <typename Derived> class timer_impl : public timer
{
-
+ protected:
+ virtual rearm expired(eventloop_t &loop, int expiry_count) override
+ {
+ return static_cast<Derived *>(this)->timer_expiry(loop, expiry_count);
+ }
};
std::unordered_set<timer *> active_timers;