return true;
}
- if (contains({shutdown_type_t::CONTINUE, shutdown_type_t::HALT,
+ if (contains({shutdown_type_t::REMAIN, shutdown_type_t::HALT,
shutdown_type_t::POWEROFF, shutdown_type_t::REBOOT}, rbuf[1])) {
auto sd_type = static_cast<shutdown_type_t>(rbuf[1]);
}
shutdown_type_t shutdown_type = services->get_shutdown_type();
+ if (shutdown_type == shutdown_type_t::REMAIN) {
+ goto event_loop;
+ }
if (am_pid_one) {
log_msg_begin(loglevel_t::INFO, "No more active services.");
else if (shutdown_type == shutdown_type_t::POWEROFF) {
log_msg_end(" Will power down.");
}
- else {
- log_msg_end(" Re-initiating boot sequence.");
- }
}
log_flush_timer.arm_timer_rel(event_loop, timespec{5,0}); // 5 seconds
close_control_socket();
if (am_pid_one) {
- if (shutdown_type == shutdown_type_t::CONTINUE) {
- // It could be that we started in single user mode, and the
- // user has now exited the shell. We'll try and re-start the
- // boot process...
+ if (shutdown_type == shutdown_type_t::NONE) {
+ // Services all stopped but there was no shutdown issued. Inform user, wait for ack, and
+ // re-start boot sequence.
+ std::cout << "No shutdown was requested; boot failure? Will re-run boot sequence." << std::endl;
+ sync(); // Sync to minimise data loss if user elects to power off / hard reset
+ wait_for_user_input();
try {
services->start_service("boot");
goto event_loop; // yes, the "evil" goto
catch (...) {
// Now what do we do? try to reboot, but wait for user ack to avoid boot loop.
log(loglevel_t::ERROR, "Could not start 'boot' service. Will attempt reboot.");
- wait_for_user_input();
shutdown_type = shutdown_type_t::REBOOT;
}
}
/* Shutdown types */
enum class shutdown_type_t {
- CONTINUE, // Continue normal boot sequence (used after single-user shell)
+ NONE, // No explicit shutdown
+ REMAIN, // Continue running with no services
HALT, // Halt system without powering down
POWEROFF, // Power off system
REBOOT // Reboot system
std::list<service_record *> records;
bool restart_enabled; // whether automatic restart is enabled (allowed)
- shutdown_type_t shutdown_type = shutdown_type_t::CONTINUE; // Shutdown type, if stopping
+ shutdown_type_t shutdown_type = shutdown_type_t::NONE; // Shutdown type, if stopping
// Services waiting for exclusive access to the console
dlist<service_record, extract_console_queue> console_queue;
return shutdown_type;
}
+ // Set the shutdown type to the specified type, without issuing a shutdown order. If all services
+ // stop, the shutdown type determines the action that Dinit will take.
+ void set_shutdown_type(shutdown_type_t new_shutdown_type) noexcept
+ {
+ shutdown_type = new_shutdown_type;
+ }
+
// Get an identifier for the run-time type of the service set (similar to typeid, but without
// requiring RTTI to be enabled during compilation).
virtual int get_set_type_id()