bsp->pid = -1;
bsp->handle_exit_status(bp_sys::exit_status(false, true, signo));
}
+
+ static int get_notification_fd(base_process_service *bsp)
+ {
+ return bsp->notification_fd;
+ }
};
namespace bp_sys {
sset.remove_service(&p);
}
+// Test start with readiness notification
+void test_proc_notify_start()
+{
+ 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_notification_fd(3);
+ sset.add_service(&p);
+
+ p.start(true);
+ sset.process_queues();
+
+ assert(p.get_state() == service_state_t::STARTING);
+
+ base_process_service_test::exec_succeeded(&p);
+ sset.process_queues();
+
+ assert(p.get_state() == service_state_t::STARTING);
+
+ int nfd = base_process_service_test::get_notification_fd(&p);
+ assert(nfd > 0);
+
+ char notifystr[] = "ok started\n";
+ std::vector<char> rnotifystr;
+ rnotifystr.insert(rnotifystr.end(), notifystr, notifystr + sizeof(notifystr));
+ bp_sys::supply_read_data(nfd, std::move(rnotifystr));
+
+ event_loop.regd_fd_watchers[nfd]->fd_event(event_loop, nfd, dasynq::IN_EVENTS);
+
+ assert(p.get_state() == service_state_t::STARTED);
+ assert(event_loop.active_timers.size() == 0);
+
+ sset.remove_service(&p);
+}
+
// Unexpected termination
void test_proc_unexpected_term()
{
init_service_defaults(p);
sset.add_service(&p);
- service_record ts {&sset, "test-service-1", service_type_t::INTERNAL, {{&p, dependency_type::WAITS_FOR}} };
+ service_record ts {&sset, "test-service-1", service_type_t::INTERNAL,
+ {{&p, dependency_type::WAITS_FOR}} };
ts.start(true);
sset.process_queues();
sset.remove_service(&p);
}
-
// Test stop timeout
void test_proc_stop_timeout()
{
sset.add_service(&p);
service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {{&p, REG}});
- service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{&p, REG}, {s2, REG}});
+ service_record *s3 = new service_record(&sset, "test-service-3",
+ service_type_t::INTERNAL, {{&p, REG}, {s2, REG}});
sset.add_service(s2);
sset.add_service(s3);
sset.add_service(&p);
service_record *s2 = new service_record(&sset, "test-service-2", service_type_t::INTERNAL, {});
- service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL, {{s2, REG}, {&p, REG}});
- service_record *s4 = new service_record(&sset, "test-service-4", service_type_t::INTERNAL, {{&p, REG}, {s3, REG}});
+ service_record *s3 = new service_record(&sset, "test-service-3", service_type_t::INTERNAL,
+ {{s2, REG}, {&p, REG}});
+ service_record *s4 = new service_record(&sset, "test-service-4", service_type_t::INTERNAL,
+ {{&p, REG}, {s3, REG}});
sset.add_service(s2);
sset.add_service(s3);
sset.add_service(s4);
int main(int argc, char **argv)
{
RUN_TEST(test_proc_service_start, " ");
+ RUN_TEST(test_proc_notify_start, " ");
RUN_TEST(test_proc_unexpected_term, " ");
RUN_TEST(test_term_via_stop, " ");
RUN_TEST(test_term_via_stop2, " ");
public:
void add_watch(eventloop_t &loop, int fd, int events, bool enable = true)
{
+ if (loop.regd_fd_watchers.find(fd) != loop.regd_fd_watchers.end()
+ || loop.regd_bidi_watchers.find(fd) != loop.regd_bidi_watchers.end()) {
+ throw std::string("must not add_watch when already active");
+ }
watched_fd = fd;
+ loop.regd_fd_watchers[fd] = this;
}
int get_watched_fd() noexcept
void deregister(eventloop_t &loop) noexcept
{
-
+ loop.regd_fd_watchers.erase(watched_fd);
+ watched_fd = -1;
}
+
+ virtual rearm fd_event(eventloop_t & loop, int fd, int flags) = 0;
};
template <typename Derived> class fd_watcher_impl : public fd_watcher
std::unordered_set<timer *> active_timers;
std::map<int, bidi_fd_watcher *> regd_bidi_watchers;
+ std::map<int, fd_watcher *> regd_fd_watchers;
};
inline void open_control_socket(bool report_ro_failure = true) noexcept