From 7838528da7e7f425adb0301e25d2fc6ad144325d Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Tue, 19 Jun 2018 22:40:40 +0100 Subject: [PATCH] dinitctl: show process id and console state in service list. --- src/control.cc | 28 +++++++++++++++++++++----- src/dinitctl.cc | 39 ++++++++++++++++++++++++++++++++----- src/includes/control.h | 2 +- src/includes/dinit-client.h | 2 +- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/control.cc b/src/control.cc index 15e7ca2..a7544be 100644 --- a/src/control.cc +++ b/src/control.cc @@ -1,6 +1,9 @@ #include "control.h" #include "service.h" +// Server-side control protocol implementation. This implements the functionality that allows +// clients (such as dinitctl) to query service state and issue commands to control services. + namespace { constexpr auto OUT_EVENTS = dasynq::OUT_EVENTS; constexpr auto IN_EVENTS = dasynq::IN_EVENTS; @@ -312,22 +315,37 @@ bool control_conn_t::list_services() for (auto sptr : slist) { std::vector pkt_buf; + int hdrsize = 8 + std::max(sizeof(int), sizeof(pid_t)); + const std::string &name = sptr->get_name(); int nameLen = std::min((size_t)256, name.length()); - pkt_buf.resize(8 + nameLen); + pkt_buf.resize(hdrsize + nameLen); pkt_buf[0] = DINIT_RP_SVCINFO; pkt_buf[1] = nameLen; pkt_buf[2] = static_cast(sptr->get_state()); pkt_buf[3] = static_cast(sptr->get_target_state()); - pkt_buf[4] = 0; // reserved - pkt_buf[5] = 0; - pkt_buf[6] = 0; + char b0 = sptr->is_waiting_for_console() ? 1 : 0; + b0 |= sptr->has_console() ? 2 : 0; + pkt_buf[4] = b0; + pkt_buf[5] = static_cast(sptr->get_stop_reason()); + + pkt_buf[6] = 0; // reserved pkt_buf[7] = 0; + // Next: either the exit status, or the process ID + if (sptr->get_state() != service_state_t::STOPPED) { + pid_t proc_pid = sptr->get_pid(); + memcpy(pkt_buf.data() + 8, &proc_pid, sizeof(proc_pid)); + } + else { + int exit_status = sptr->get_exit_status(); + memcpy(pkt_buf.data() + 8, &exit_status, sizeof(exit_status)); + } + for (int i = 0; i < nameLen; i++) { - pkt_buf[8+i] = name[i]; + pkt_buf[hdrsize+i] = name[i]; } if (! queue_packet(std::move(pkt_buf))) return false; diff --git a/src/dinitctl.cc b/src/dinitctl.cc index 6be9da9..eeb2592 100644 --- a/src/dinitctl.cc +++ b/src/dinitctl.cc @@ -536,14 +536,30 @@ static int list_services(int socknum, cpbuffer_t &rbuffer) wait_for_reply(rbuffer, socknum); while (rbuffer[0] == DINIT_RP_SVCINFO) { - fill_buffer_to(rbuffer, socknum, 8); + int hdrsize = 8 + std::max(sizeof(int), sizeof(pid_t)); + fill_buffer_to(rbuffer, socknum, hdrsize); int nameLen = rbuffer[1]; service_state_t current = static_cast(rbuffer[2]); service_state_t target = static_cast(rbuffer[3]); - fill_buffer_to(rbuffer, socknum, nameLen + 8); + int console_flags = rbuffer[4]; + bool has_console = (console_flags & 2) != 0; + bool waiting_console = (console_flags & 1) != 0; - char *name_ptr = rbuffer.get_ptr(8); + // stopped_reason_t stop_reason = static_cast(rbuffer[5]); + + pid_t service_pid; + int exit_status; + if (current != service_state_t::STOPPED) { + rbuffer.extract((char *)&service_pid, 8, sizeof(service_pid)); + } + else { + rbuffer.extract((char *)&exit_status, 8, sizeof(exit_status)); + } + + fill_buffer_to(rbuffer, socknum, nameLen + hdrsize); + + char *name_ptr = rbuffer.get_ptr(hdrsize); int clength = std::min(rbuffer.get_contiguous_length(name_ptr), nameLen); string name = string(name_ptr, clength); @@ -569,9 +585,22 @@ static int list_services(int socknum, cpbuffer_t &rbuffer) cout << (current == service_state_t::STOPPED ? "-" : " "); cout << (target == service_state_t::STOPPED ? "}" : " "); - cout << "] " << name << endl; + cout << "] " << name; + + if (current != service_state_t::STOPPED && service_pid != -1) { + cout << " (pid: " << service_pid << ")"; + } + + if (has_console) { + cout << " (has console)"; + } + else if (waiting_console) { + cout << " (waiting for console)"; + } + + cout << endl; - rbuffer.consume(8 + nameLen); + rbuffer.consume(hdrsize + nameLen); wait_for_reply(rbuffer, socknum); } diff --git a/src/includes/control.h b/src/includes/control.h index eae7a89..ee9d9f8 100644 --- a/src/includes/control.h +++ b/src/includes/control.h @@ -218,7 +218,7 @@ class control_conn_t : private service_listener }; -static dasynq::rearm control_conn_cb(eventloop_t * loop, control_conn_watcher * watcher, int revents) +inline 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") diff --git a/src/includes/dinit-client.h b/src/includes/dinit-client.h index 0fff4a4..0492408 100644 --- a/src/includes/dinit-client.h +++ b/src/includes/dinit-client.h @@ -113,7 +113,7 @@ inline void write_all_x(int fd, const void *buf, size_t count) } // Check the protocol version is compatible with the client. -// minverison - minimum protocol version that client can speak +// minversion - minimum protocol version that client can speak // version - maximum protocol version that client can speak // rbuffer, fd - communication buffer and socket // returns: the actual protocol version -- 2.25.1