aboutsummaryrefslogtreecommitdiffstats
path: root/include/jau/basic_algos.hpp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2022-05-13 01:26:43 +0200
committerSven Gothel <[email protected]>2022-05-13 01:26:43 +0200
commite6ada6040b738df03c8cc6199a6375cf3aa67e44 (patch)
treec57848ba437f35fb564646830248ba0a40830b1d /include/jau/basic_algos.hpp
parente5421ff1dfed4d26ac40542252aba0c4bb1094b5 (diff)
Fix call_on_release: Skip calling `release_func` if resource has been marked orderly released, avoid use after free.
Detected via valgrind.
Diffstat (limited to 'include/jau/basic_algos.hpp')
-rw-r--r--include/jau/basic_algos.hpp17
1 files changed, 14 insertions, 3 deletions
diff --git a/include/jau/basic_algos.hpp b/include/jau/basic_algos.hpp
index 10efa69..569f48a 100644
--- a/include/jau/basic_algos.hpp
+++ b/include/jau/basic_algos.hpp
@@ -49,27 +49,38 @@ namespace jau {
* jau::relaxed_atomic_bool is_running = true;
*
* void some_thread_func() {
- * thread_local jau::call_on_release lili([&]() {
+ * thread_local jau::call_on_release thread_cleanup([&]() {
* is_running = false;
* });
* ...
* do some work here, which might get cancelled
* ..
+ * thread_cleanup.set_released(); // mark orderly release
* }
* </pre>
* </p>
* @tparam UnaryFunction user provided function to be called @ dtor
+ * @see jau::service_runner
*/
template <class UnaryFunction> class call_on_release {
private:
UnaryFunction f;
+ jau::sc_atomic_bool released;
public:
- call_on_release(UnaryFunction release_func) noexcept : f(release_func) {}
- ~call_on_release() noexcept { f(); }
+ call_on_release(UnaryFunction release_func) noexcept
+ : f(release_func), released(false) {}
+ ~call_on_release() noexcept {
+ if( !released ) { f(); }
+ }
call_on_release(const call_on_release&) = delete;
call_on_release& operator=(const call_on_release&) = delete;
call_on_release& operator=(const call_on_release&) volatile = delete;
+
+ /** Mark the resource being orderly released, `release_func()` will not be called and *use after free* avoided. */
+ void set_released() noexcept { released = true; }
+ /** Query whethr the resource has been orderly released. */
+ bool is_released() const noexcept { return released; }
};
/****************************************************************************************