aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/transaction.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-28 17:43:18 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-28 17:43:18 +1000
commit52cf410d3cfcf0cae81b47c90097867c4e4d8564 (patch)
tree08ba3ef9af21a120b380401dbed5e4a5badce996 /sway/desktop/transaction.c
parentMerge pull request #2370 from RyanDwyer/transactions-use-after-free (diff)
downloadsway-52cf410d3cfcf0cae81b47c90097867c4e4d8564.tar.gz
sway-52cf410d3cfcf0cae81b47c90097867c4e4d8564.tar.zst
sway-52cf410d3cfcf0cae81b47c90097867c4e4d8564.zip
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/desktop/transaction.c')
-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(
344 344
345 } 345 }
346 346
347 // If all views are ready, apply the transaction.
348 // If the transaction has timed out then its num_waiting will be 0 already. 347 // If the transaction has timed out then its num_waiting will be 0 already.
349 if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) { 348 if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) {
350 if (!txn_debug) { 349 if (!txn_debug) {
351 wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction); 350 wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction);
352 wl_event_source_timer_update(transaction->timer, 0); 351 wl_event_source_timer_update(transaction->timer, 0);
353 transaction_progress_queue();
354 } 352 }
355 } 353 }
356} 354}
@@ -364,15 +362,10 @@ static void set_instructions_ready(struct sway_view *view, int index) {
364 struct sway_transaction_instruction *instruction = 362 struct sway_transaction_instruction *instruction =
365 view->swayc->instructions->items[i]; 363 view->swayc->instructions->items[i];
366 if (!instruction->ready) { 364 if (!instruction->ready) {
367 // set_instruction_ready can remove instructions from the list we're
368 // iterating
369 size_t length = view->swayc->instructions->length;
370 set_instruction_ready(instruction); 365 set_instruction_ready(instruction);
371 size_t num_removed = length - view->swayc->instructions->length;
372 i -= num_removed;
373 index -= num_removed;
374 } 366 }
375 } 367 }
368 transaction_progress_queue();
376} 369}
377 370
378void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) { 371void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) {