main: fix double free of screen_off_bg lv_obj

If the Alarm is set, then switch away from the Alarm Screen and turn off
display to get the "Screen is OFF" overlay. When the alarm rings the
Screen is switched to the Alarm Screen, which triggers the current
screen (for example the Clock/WatchFace) to issue an `lv_obj_clean()`
call. This call removes the `screen_off_bg` object, before the main
`refresh_sceen()` of the simulator can do it. Later the simulator tries
to remove the `screen_off_bg` object again, which is a double-free of
memory resulting in a segfault.

To prevent this segfault add a callback to the `screen_off_bg` callback
which informs the simulator, that the object has already been removed.

Fixes: https://github.com/InfiniTimeOrg/InfiniSim/issues/8
This commit is contained in:
Reinhold Gschweicher 2022-03-01 22:43:33 +01:00
parent 2b8b4edba3
commit 8bc308b4e1
1 changed files with 13 additions and 0 deletions

View File

@ -617,6 +617,17 @@ public:
std::cout << "unhandled screen_idx: " << int(screen_idx) << std::endl; std::cout << "unhandled screen_idx: " << int(screen_idx) << std::endl;
} }
} }
static void screen_off_delete_cb(lv_obj_t *obj, lv_event_t event)
{
if (event == LV_EVENT_DELETE) {
auto* fw = static_cast<Framework*>(obj->user_data);
if (obj == fw->screen_off_bg)
{
// on delete make sure to not double free the screen_off objects
fw->screen_off_created = false;
}
}
}
// render the current status of the simulated controller // render the current status of the simulated controller
void refresh_screen() { void refresh_screen() {
const Pinetime::Controllers::BrightnessController::Levels level = brightnessController.Level(); const Pinetime::Controllers::BrightnessController::Levels level = brightnessController.Level();
@ -627,6 +638,8 @@ public:
lv_obj_set_size(screen_off_bg, 240, 240); lv_obj_set_size(screen_off_bg, 240, 240);
lv_obj_set_pos(screen_off_bg, 0, 0); lv_obj_set_pos(screen_off_bg, 0, 0);
lv_obj_set_style_local_bg_color(screen_off_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_bg_color(screen_off_bg, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
screen_off_bg->user_data = this; // add callback to prevent double free through Alarm Screen
lv_obj_set_event_cb(screen_off_bg, screen_off_delete_cb);
screen_off_label = lv_label_create(lv_scr_act(), nullptr); screen_off_label = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(screen_off_label, "Screen is OFF"); lv_label_set_text_static(screen_off_label, "Screen is OFF");
lv_obj_align(screen_off_label, nullptr, LV_ALIGN_CENTER, 0, -20); lv_obj_align(screen_off_label, nullptr, LV_ALIGN_CENTER, 0, -20);