From 0565b11c199e419b6827a711b3aae01c85cfc681 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Feb 2017 12:23:53 -0600 Subject: [PATCH] common/TrackedOp: make TrackedOp::reset_desc() safe It is possible for a reset_desc() call to clear the desc char* while get_desc() is executing such that it will return a nullptr to the caller. This can lead to bad results, like a crash in std::string() (which does not like to take null). Fix this by not clearing desc. Instead, set a separate flag to indicate that desc should be (safely) rebuilt on the next get_desc() call. Fixes: http://tracker.ceph.com/issues/19110 Signed-off-by: Sage Weil --- src/common/TrackedOp.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/TrackedOp.h b/src/common/TrackedOp.h index db014a350639..31439dc23ff0 100644 --- a/src/common/TrackedOp.h +++ b/src/common/TrackedOp.h @@ -188,6 +188,7 @@ protected: mutable string desc_str; ///< protected by lock mutable const char *desc = nullptr; ///< readable without lock + mutable atomic want_new_desc = {false}; TrackedOp(OpTracker *_tracker, const utime_t& initiated) : tracker(_tracker), @@ -235,7 +236,7 @@ public: } const char *get_desc() const { - if (!desc) { + if (!desc || want_new_desc.load()) { Mutex::Locker l(lock); _gen_desc(); } @@ -247,10 +248,11 @@ private: _dump_op_descriptor_unlocked(ss); desc_str = ss.str(); desc = desc_str.c_str(); + want_new_desc = false; } public: void reset_desc() { - desc = nullptr; + want_new_desc = true; } const utime_t& get_initiated() const { -- 2.47.3