Skip to content
This repository has been archived by the owner on Apr 6, 2019. It is now read-only.

Heap-use-after-free when deleting while callback is still running #192

Open
boflexman opened this issue Aug 2, 2018 · 1 comment
Open

Comments

@boflexman
Copy link

Hey together,

currently I have a problem regarding the usage of two parallel redis connections from an application.
After usage, I want to close the connection by calling the function
--> client.disconnect(true);

From this point on, my address sanitizer build says there is a heap-use-after-free problem:


  • 08/02/18 13:27:03 INFO [Redis] Disconnection of redis client... // Object 1 client.disconnect(true)
  • ~Client: 0x0x61a00001e098 Running 0x0x61a00001e4f0 // Object 1 is deleted via destructor
  • 08/02/18 13:27:03 INFO [Redis] Disconnection of redis client... // Object 2 client.disconnect(true)
  • ~Client: 0x0x61a00001da98 Running 0x0x61a00001def0 // Object 2 is deleted via destructor
  • Callback 0x0x61a00001e098 Running 0x0x61a00001e4f0 // Object 1 is still in use
    =================================================================
    ==13580==ERROR: AddressSanitizer: heap-use-after-free on address 0x61a00001e4f0 at pc 0x0000006b8b79 bp 0x7fd5fe217d30 sp 0x7fd5fe217d20
    WRITE of size 4 at 0x61a00001e4f0 thread T3

One can see that two redis client objects get disconnected and destroyed, but nevertheless we receive a callback of the already destroyed object.

Furthermore, one can see that this depends on the below mentioned function client::clear_callbacks


void
client::clear_callbacks(void) {
if (m_commands.empty()) {
return;
}

//! dequeue commands and move them to a local variable
std::queue<command_request> commands = std::move(m_commands);

m_callbacks_running += __CPP_REDIS_LENGTH(commands.size());

std::thread t(= mutable {
while (!commands.empty()) {
const auto& callback = commands.front().callback;

  if (callback) {
    reply r = {"network failure", reply::string_type::error};
    callback(r);
  }

  --m_callbacks_running;        // 0x0x61a00001e4f0           
  commands.pop();
}
m_sync_condvar.notify_all();

});
t.detach();
}


The function clear_callbacks gets called while both objects are still valid.
After calling the destructor of the objects, we get a callback from the thread created inside the function.

If there are any further questions, don´t hesitate to ask me.

Thanks in advance,
Andy

@skeetor
Copy link

skeetor commented Sep 6, 2018

I submitted a PR to fix this issue as I tracked it down to callbacks not being completed while the object is already destroyed.
Looks like this issue #198 is reporting the same problem.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants