Schedule a client to free it at a safe time in the serverCron() function. * This function is useful when we need to terminate a client but we are in * a context where calling freeClient() is not possible, because the client * should be valid for the continuation of the flow of the program. */
| 1757 | * a context where calling freeClient() is not possible, because the client |
| 1758 | * should be valid for the continuation of the flow of the program. */ |
| 1759 | void freeClientAsync(client *c) { |
| 1760 | /* We need to handle concurrent access to the g_pserver->clients_to_close list |
| 1761 | * only in the freeClientAsync() function, since it's the only function that |
| 1762 | * may access the list while Redis uses I/O threads. All the other accesses |
| 1763 | * are in the context of the main thread while the other threads are |
| 1764 | * idle. */ |
| 1765 | if (c->flags & CLIENT_CLOSE_ASAP || c->flags & CLIENT_LUA) return; // check without the lock first |
| 1766 | std::lock_guard<decltype(c->lock)> clientlock(c->lock); |
| 1767 | if (c->flags & CLIENT_CLOSE_ASAP || c->flags & CLIENT_LUA) return; // race condition after we acquire the lock |
| 1768 | c->flags |= CLIENT_CLOSE_ASAP; |
| 1769 | c->repl_down_since = g_pserver->unixtime; |
| 1770 | std::unique_lock<fastlock> ul(g_lockasyncfree); |
| 1771 | listAddNodeTail(g_pserver->clients_to_close,c); |
| 1772 | } |
| 1773 | |
| 1774 | int freeClientsInAsyncFreeQueue(int iel) { |
| 1775 | serverAssert(GlobalLocksAcquired()); |
no test coverage detected