aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
authorRyan Dwyer <ryandwyer1@gmail.com>2018-07-28 17:43:18 +1000
committerRyan Dwyer <ryandwyer1@gmail.com>2018-07-28 17:43:18 +1000
commit52cf410d3cfcf0cae81b47c90097867c4e4d8564 (patch)
tree08ba3ef9af21a120b380401dbed5e4a5badce996 /sway
parent92a4bc646a52b1715f4885d7459c07b7a26a2d21 (diff)
Second attempt at fixing transaction use-after-free
The solution used in 073ac425d5bf6f6393eb91d9b5f84e3caa68f511 doesn't work in all cases because the freed instruction might be ahead in the list, not necessarily behind. The new solution delays running the queue until after the loop has finished iterating, thus avoiding the problem completely.
Diffstat (limited to 'sway')
-rw-r--r--sway/desktop/transaction.c9
1 files changed, 1 insertions, 8 deletions
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 0a24c4fc..ccda1963 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -344,13 +344,11 @@ static void set_instruction_ready(
}
- // If all views are ready, apply the transaction.
// If the transaction has timed out then its num_waiting will be 0 already.
if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) {
if (!txn_debug) {
wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction);
wl_event_source_timer_update(transaction->timer, 0);
- transaction_progress_queue();
}
}
}
@@ -364,15 +362,10 @@ static void set_instructions_ready(struct sway_view *view, int index) {
struct sway_transaction_instruction *instruction =
view->swayc->instructions->items[i];
if (!instruction->ready) {
- // set_instruction_ready can remove instructions from the list we're
- // iterating
- size_t length = view->swayc->instructions->length;
set_instruction_ready(instruction);
- size_t num_removed = length - view->swayc->instructions->length;
- i -= num_removed;
- index -= num_removed;
}
}
+ transaction_progress_queue();
}
void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) {