Commit 18bd75c
authored
future: Fix double callback execution (#468)
`ResolvableFuture::set_callback` first set a callback under lock,
released the lock, and then checked if result is set. If it is, then it
invoked the callback.
The other path for callback calling is in future execution: when setting
the result (under lock) new_from_future also reads a callback. If it
exsits, then it is called.
the following race is possible:
- `set_callback` sets callback, releases lock
- `new_from_future` produces result, sees the callback, calls it
- `set_callback` checks for the result, sees it exists, calls the
callback.
This results in double callback execution, potentially causing UB and
other issues.
This commit fixes that: in `set_callback`, while still under lock, we
check if callback should be called. Then outside of lock we call it if
needed. It is important to call the callback outside the lock, to avoid
various deadlocks.
Fixes: https://scylladb.atlassian.net/browse/CUSTOMER-4091 file changed
Lines changed: 5 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
424 | 424 | | |
425 | 425 | | |
426 | 426 | | |
427 | | - | |
| 427 | + | |
428 | 428 | | |
429 | 429 | | |
430 | 430 | | |
| |||
434 | 434 | | |
435 | 435 | | |
436 | 436 | | |
437 | | - | |
438 | 437 | | |
439 | | - | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
440 | 442 | | |
441 | 443 | | |
442 | 444 | | |
| |||
0 commit comments