Both L2TableCache and QCOWFormat can be destroyed after the completion
for the last L2 cache request is posted, particularly so in unit tests.
The strand destructor doesn't drain the handler queue in any way but
merely ensures that previously posted handlers would get dispatched in
a non-concurrent fashion. As a result, use-after-free can ensue when
execute_request() unnecessarily dispatches itself for the last time.
Fixes: https://tracker.ceph.com/issues/75378
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
ceph_assert(false);
}
+ requests.pop_front();
+ bool more = !requests.empty();
+
// complete the L2 cache request
+ // expect to be destroyed after posting completion if there are no
+ // more requests
boost::asio::post(*qcow_format->m_image_ctx->asio_engine,
[r, ctx=request.on_finish]() { ctx->complete(r); });
- requests.pop_front();
// process next request (if any)
- dispatch_request();
+ if (more) {
+ dispatch_request();
+ }
}
int l2_table_lookup(uint64_t l2_offset,