From: Casey Bodley Date: Thu, 8 Aug 2019 14:06:17 +0000 (-0400) Subject: rgw: http client drops mutex before suspending coroutine X-Git-Tag: v15.1.0~1907^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F29553%2Fhead;p=ceph.git rgw: http client drops mutex before suspending coroutine the lock can't be held over async_wait(), because the call to finish() won't be able to reacquire the lock in order to fire the completion. coroutines may also resume on a different thread, and you can't unlock a mutex that was locked on another thread Reported-by: Yuval Lifshitz Signed-off-by: Casey Bodley --- diff --git a/src/rgw/rgw_http_client.cc b/src/rgw/rgw_http_client.cc index 7c0c77e341cc..fccc52e6e62b 100644 --- a/src/rgw/rgw_http_client.cc +++ b/src/rgw/rgw_http_client.cc @@ -60,12 +60,14 @@ struct rgw_http_req_data : public RefCountedObject { auto async_wait(ExecutionContext& ctx, CompletionToken&& token) { boost::asio::async_completion init(token); auto& handler = init.completion_handler; - completion = Completion::create(ctx.get_executor(), std::move(handler)); + { + std::unique_lock l{lock}; + completion = Completion::create(ctx.get_executor(), std::move(handler)); + } return init.result.get(); } int wait(optional_yield y) { - std::unique_lock l{lock}; if (done) { return ret; } @@ -82,6 +84,7 @@ struct rgw_http_req_data : public RefCountedObject { dout(20) << "WARNING: blocking http request" << dendl; } #endif + std::unique_lock l{lock}; cond.wait(l); return ret; }