Skip to content

Commit 0277fd8

Browse files
muhomorrthestinger
authored andcommitted
add auto-reboot implementation
1 parent 69e57ec commit 0277fd8

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

init/property_service.cpp

+83
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,82 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value,
524524
return PROP_SUCCESS;
525525
}
526526

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

645+
if (name == "sys.auto_reboot_ctl") {
646+
int res = auto_reboot_handle_property_set(value);
647+
return {res};
648+
}
649+
569650
return PropertySet(name, value, socket, error);
570651
}
571652

@@ -1438,6 +1519,8 @@ static void PropertyServiceThread() {
14381519
LOG(FATAL) << result.error();
14391520
}
14401521

1522+
auto_reboot_timer_init();
1523+
14411524
while (true) {
14421525
auto epoll_result = epoll.Wait(std::nullopt);
14431526
if (!epoll_result.ok()) {

0 commit comments

Comments
 (0)