|
16 | 16 |
|
17 | 17 | #include "sw/redis++/event_loop.h" |
18 | 18 | #include <cassert> |
| 19 | +#include <chrono> |
| 20 | +#include <thread> |
19 | 21 | #include <hiredis/adapters/libuv.h> |
20 | 22 | #include "sw/redis++/async_connection.h" |
21 | 23 |
|
@@ -208,26 +210,42 @@ void EventLoop::LoopDeleter::operator()(uv_loop_t *loop) const { |
208 | 210 | // How to correctly close an event loop: |
209 | 211 | // https://stackoverflow.com/questions/25615340/closing-libuv-handles-correctly |
210 | 212 | // TODO: do we need to call this? Since we always has 2 async_t handles. |
211 | | - if (uv_loop_close(loop) == 0) { |
212 | | - delete loop; |
| 213 | + //if (uv_loop_close(loop) == 0) { |
| 214 | + // delete loop; |
| 215 | + // |
| 216 | + // return; |
| 217 | + //} |
213 | 218 |
|
214 | | - return; |
215 | | - } |
| 219 | + assert(loop->data != nullptr); |
216 | 220 |
|
217 | 221 | uv_walk(loop, |
218 | | - [](uv_handle_t *handle, void *) { |
| 222 | + [](uv_handle_t *handle, void *arg) { |
219 | 223 | if (handle != nullptr) { |
220 | | - // We don't need to release handle's memory in close callback, |
221 | | - // since we'll release the memory in EventLoop's destructor. |
222 | | - uv_close(handle, nullptr); |
| 224 | + auto *event_loop = static_cast<EventLoop *>(arg); |
| 225 | + |
| 226 | + assert(event_loop != nullptr); |
| 227 | + |
| 228 | + if (handle == reinterpret_cast<uv_handle_t *>(event_loop->_event_async.get()) || |
| 229 | + handle == reinterpret_cast<uv_handle_t *>(event_loop->_stop_async.get())) { |
| 230 | + // We don't need to release handle's memory in close callback, |
| 231 | + // since we'll release the memory in EventLoop's destructor. |
| 232 | + uv_close(handle, nullptr); |
| 233 | + } |
223 | 234 | } |
224 | 235 | }, |
225 | | - nullptr); |
| 236 | + loop->data); |
226 | 237 |
|
227 | 238 | // Ensure uv_walk's callback to be called. |
228 | 239 | uv_run(loop, UV_RUN_DEFAULT); |
229 | 240 |
|
230 | | - uv_loop_close(loop); |
| 241 | + for (auto idx = 0; idx < 10; ++idx) { |
| 242 | + if (uv_loop_close(loop) == 0) { |
| 243 | + break; |
| 244 | + } |
| 245 | + |
| 246 | + // maybe hiredis does not close the handle yet? wait a while. |
| 247 | + std::this_thread::sleep_for(std::chrono::milliseconds(100)); |
| 248 | + } |
231 | 249 |
|
232 | 250 | delete loop; |
233 | 251 | } |
@@ -271,14 +289,16 @@ EventLoop::UvAsyncUPtr EventLoop::_create_uv_async(AsyncCallback callback) { |
271 | 289 | return uv_async; |
272 | 290 | } |
273 | 291 |
|
274 | | -EventLoop::LoopUPtr EventLoop::_create_event_loop() const { |
| 292 | +EventLoop::LoopUPtr EventLoop::_create_event_loop() { |
275 | 293 | auto *loop = new uv_loop_t; |
276 | 294 | auto err = uv_loop_init(loop); |
277 | 295 | if (err != 0) { |
278 | 296 | delete loop; |
279 | 297 | throw Error("failed to initialize event loop: " + _err_msg(err)); |
280 | 298 | } |
281 | 299 |
|
| 300 | + loop->data = this; |
| 301 | + |
282 | 302 | return LoopUPtr(loop); |
283 | 303 | } |
284 | 304 |
|
|
0 commit comments