Skip to content

Commit d053937

Browse files
muhomorrthestinger
authored andcommitted
add auto-reboot implementation
1 parent 452779a commit d053937

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

init/property_service.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,82 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value,
538538
return PROP_SUCCESS;
539539
}
540540

541+
static timer_t auto_reboot_timer;
542+
static bool device_unlocked_at_least_once;
543+
static bool is_auto_reboot_timer_started;
544+
545+
static void auto_reboot_timer_callback(union sigval) {
546+
LOG(INFO) << "auto_reboot: received timer callback, rebooting";
547+
trigger_shutdown("reboot");
548+
}
549+
550+
// all of the auto_reboot_* functions, except for auto_reboot_timer_callback, are called on the
551+
// same thread
552+
553+
static void auto_reboot_timer_init() {
554+
struct sigevent sev = {};
555+
sev.sigev_notify = SIGEV_THREAD;
556+
sev.sigev_notify_function = auto_reboot_timer_callback;
557+
558+
if (int r = timer_create(CLOCK_BOOTTIME_ALARM, &sev, &auto_reboot_timer); r != 0) {
559+
LOG(FATAL) << "auto_reboot: timer_create failed: " << strerror(errno);
560+
}
561+
}
562+
563+
static void auto_reboot_timer_set(time_t duration_sec) {
564+
const time_t min_duration = 20;
565+
if (duration_sec != 0 && duration_sec < min_duration) {
566+
LOG(WARNING) << "auto_reboot: raised timer duration from " << duration_sec << " to " << min_duration << " seconds";
567+
duration_sec = min_duration;
568+
}
569+
struct itimerspec ts_dur = {};
570+
ts_dur.it_value.tv_sec = duration_sec;
571+
struct itimerspec ts_prev = {};
572+
int flags = 0;
573+
if (int r = timer_settime(auto_reboot_timer, flags, &ts_dur, &ts_prev); r != 0) {
574+
LOG(FATAL) << "auto_reboot: timer_settime failed: " << strerror(errno);
575+
}
576+
if (duration_sec > 0) {
577+
LOG(INFO) << "auto_reboot: started timer for " << duration_sec << " seconds";
578+
}
579+
LOG(DEBUG) << "auto_reboot: prev timer value: " << ts_prev.it_value.tv_sec << " seconds";
580+
}
581+
582+
static int auto_reboot_handle_property_set(const std::string& value) {
583+
LOG(DEBUG) << "auto_reboot: handle_property_set: " << value;
584+
if (value == "on_device_unlocked") {
585+
device_unlocked_at_least_once = true;
586+
if (is_auto_reboot_timer_started) {
587+
auto_reboot_timer_set(0);
588+
is_auto_reboot_timer_started = false;
589+
LOG(INFO) << "auto_reboot: on_device_unlocked: stopped timer";
590+
} else {
591+
LOG(INFO) << "auto_reboot: on_device_unlocked: no started timer";
592+
}
593+
return PROP_SUCCESS;
594+
}
595+
596+
int duration_sec = atoi(value.c_str()); // std::stoi can throw
597+
if (duration_sec <= 0 || (uint64_t) duration_sec > (uint64_t) std::numeric_limits<time_t>::max()) {
598+
LOG(WARNING) << "auto_reboot: invalid prop value: " << value;
599+
return PROP_ERROR_INVALID_VALUE;
600+
}
601+
602+
if (device_unlocked_at_least_once) {
603+
if (is_auto_reboot_timer_started) {
604+
LOG(INFO) << "auto_reboot: timer is already started, ignored request to restart it;"
605+
<< " requested timer duration: " << value << " seconds";
606+
} else {
607+
auto_reboot_timer_set((time_t) duration_sec);
608+
is_auto_reboot_timer_started = true;
609+
}
610+
} else {
611+
LOG(INFO) << "auto_reboot: device was never unlocked, skipped setting timer";
612+
}
613+
614+
return PROP_SUCCESS;
615+
}
616+
541617
// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*, or std::nullopt
542618
// if asynchronous.
543619
std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::string& value,
@@ -580,6 +656,11 @@ std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::st
580656
return {PROP_SUCCESS};
581657
}
582658

659+
if (name == "sys.auto_reboot_ctl") {
660+
int res = auto_reboot_handle_property_set(value);
661+
return {res};
662+
}
663+
583664
return PropertySet(name, value, socket, error);
584665
}
585666

@@ -1466,6 +1547,8 @@ static void PropertyServiceThread(int fd, bool listen_init) {
14661547
}
14671548
}
14681549

1550+
auto_reboot_timer_init();
1551+
14691552
while (true) {
14701553
auto epoll_result = epoll.Wait(std::nullopt);
14711554
if (!epoll_result.ok()) {

0 commit comments

Comments
 (0)