Fix race condition crashes when unmapping views

This fixes two issues which were both introduced in #2396.

First issue:
The PR changes the location of the buffer save to transaction_apply, but
puts it inside the should_configure block. For unmapping (destroying)
views, should_configure returns false so it wasn't saving the buffer. If
a frame was rendered between the unmap and the transaction applying then
it would result in a crash.

Second issue:
If a destroying view is involved in two transactions, we must not
release the buffer between the transactions because there is no live
buffer to grab any more.
This commit is contained in:
Ryan Dwyer 2018-08-02 20:54:03 +10:00
parent d6095588a1
commit 8314019f66

View file

@ -195,11 +195,18 @@ static void transaction_apply(struct sway_transaction *transaction) {
sizeof(struct sway_container_state)); sizeof(struct sway_container_state));
if (container->type == C_VIEW) { if (container->type == C_VIEW) {
if (container->sway_view->saved_buffer) { if (container->destroying) {
view_remove_saved_buffer(container->sway_view); if (container->instructions->length == 1 &&
} container->sway_view->saved_buffer) {
if (container->instructions->length > 1) { view_remove_saved_buffer(container->sway_view);
view_save_buffer(container->sway_view); }
} else {
if (container->sway_view->saved_buffer) {
view_remove_saved_buffer(container->sway_view);
}
if (container->instructions->length > 1) {
view_save_buffer(container->sway_view);
}
} }
} }
} }
@ -276,9 +283,9 @@ static void transaction_commit(struct sway_transaction *transaction) {
// mapping and its default geometry doesn't intersect an output. // mapping and its default geometry doesn't intersect an output.
struct timespec when; struct timespec when;
wlr_surface_send_frame_done(con->sway_view->surface, &when); wlr_surface_send_frame_done(con->sway_view->surface, &when);
if (!con->sway_view->saved_buffer) { }
view_save_buffer(con->sway_view); if (con->type == C_VIEW && !con->sway_view->saved_buffer) {
} view_save_buffer(con->sway_view);
} }
list_add(con->instructions, instruction); list_add(con->instructions, instruction);
} }