1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Safeguard for Ticker internal storage that may be changed during callback execution (#8820)

Temporarily move callback into the function scope and execute it from there.
Detaching would no longer destroy it, and re-scheduling would no longer be almost immediately cancelled by our code.
This commit is contained in:
Max Prokhorov 2023-01-26 15:50:14 +03:00 committed by GitHub
parent 9c4a1239da
commit e25f9e9578
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -115,6 +115,11 @@ void Ticker::_static_callback()
} }
} }
// it is technically allowed to call either schedule or detach
// *during* callback execution. allow both to happen
decltype(_callback) tmp;
std::swap(tmp, _callback);
std::visit([](auto&& callback) { std::visit([](auto&& callback) {
using T = std::decay_t<decltype(callback)>; using T = std::decay_t<decltype(callback)>;
if constexpr (std::is_same_v<T, callback_ptr_t>) { if constexpr (std::is_same_v<T, callback_ptr_t>) {
@ -122,7 +127,16 @@ void Ticker::_static_callback()
} else if constexpr (std::is_same_v<T, callback_function_t>) { } else if constexpr (std::is_same_v<T, callback_function_t>) {
callback(); callback();
} }
}, _callback); }, tmp);
// ...and move ourselves back only when object is in a valid state
// * ticker was not detached, zeroing timer pointer
// * nothing else replaced callback variant
if ((_timer == nullptr) || !std::holds_alternative<std::monostate>(_callback)) {
return;
}
std::swap(tmp, _callback);
if (_repeat) { if (_repeat) {
if (_tick) { if (_tick) {