From 23f611b5fc0fa5af3b556d9d9edbd4ce0cc8a461 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Fri, 14 Jun 2024 15:44:42 +0800 Subject: [PATCH 86/95] vnc: Fix crash when disconnected too soon Delay the destruction for 500ms, since the client might be about to bind the resources. Signed-off-by: Jeffy Chen --- libweston/backend-vnc/vnc.c | 50 ++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/libweston/backend-vnc/vnc.c b/libweston/backend-vnc/vnc.c index 1589d28..bdbc663 100644 --- a/libweston/backend-vnc/vnc.c +++ b/libweston/backend-vnc/vnc.c @@ -122,6 +122,9 @@ struct vnc_peer { enum nvnc_button_mask last_button_mask; struct wl_list link; + + int64_t create_ms; + struct wl_event_source *cleanup_timer; }; struct vnc_head { @@ -513,21 +516,45 @@ vnc_handle_auth(const char *username, const char *password, void *userdata) return weston_authenticate_user(username, password); } -static void -vnc_client_cleanup(struct nvnc_client *client) +static int +peer_cleanup_handler(void *data) { - struct vnc_peer *peer = nvnc_get_userdata(client); - struct vnc_output *output = peer->backend->output; + struct vnc_peer *peer = data; + + wl_event_source_remove(peer->cleanup_timer); - wl_list_remove(&peer->link); weston_seat_release_keyboard(peer->seat); weston_seat_release_pointer(peer->seat); weston_seat_release(peer->seat); free(peer); - weston_log("VNC Client disconnected\n"); + + return 1; +} + +static void +vnc_client_cleanup(struct nvnc_client *client) +{ + struct vnc_peer *peer = nvnc_get_userdata(client); + struct vnc_backend *backend = peer->backend; + struct vnc_output *output = backend->output; + struct timespec now; + int delay_ms; + + wl_list_remove(&peer->link); if (output && wl_list_empty(&output->peers)) weston_output_power_off(&output->base); + + weston_log("VNC Client disconnected\n"); + + /** + * HACK: Avoid destroying peer too soon, since the client might be about + * to bind the peer's resources. + */ + weston_compositor_read_presentation_clock(backend->compositor, &now); + delay_ms = peer->create_ms + 500 - timespec_to_msec(&now); + wl_event_source_timer_update(peer->cleanup_timer, + delay_ms > 0 ? delay_ms : 1); } static struct weston_pointer * @@ -843,6 +870,8 @@ vnc_new_client(struct nvnc_client *client) struct vnc_output *output = backend->output; struct vnc_peer *peer; const char *seat_name = "VNC Client"; + struct wl_event_loop *loop; + struct timespec now; weston_log("New VNC client connected\n"); @@ -863,6 +892,15 @@ vnc_new_client(struct nvnc_client *client) nvnc_set_userdata(client, peer, NULL); nvnc_set_client_cleanup_fn(client, vnc_client_cleanup); + loop = wl_display_get_event_loop(backend->compositor->wl_display); + peer->cleanup_timer = wl_event_loop_add_timer(loop, + peer_cleanup_handler, + peer); + + weston_compositor_read_presentation_clock(backend->compositor, + &now); + peer->create_ms = timespec_to_msec(&now); + /* * Make up for repaints that were skipped when no clients were * connected. -- 2.20.1