| 6898 | } |
| 6899 | |
| 6900 | void executeWithoutGlobalLock(std::function<void()> func) { |
| 6901 | serverAssert(GlobalLocksAcquired()); |
| 6902 | |
| 6903 | std::vector<client*> vecclients; |
| 6904 | listIter li; |
| 6905 | listNode *ln; |
| 6906 | listRewind(g_pserver->clients, &li); |
| 6907 | |
| 6908 | // All client locks must be acquired *after* the global lock is reacquired to prevent deadlocks |
| 6909 | // so unlock here, and save them for reacquisition later |
| 6910 | while ((ln = listNext(&li)) != nullptr) |
| 6911 | { |
| 6912 | client *c = (client*)listNodeValue(ln); |
| 6913 | if (c->lock.fOwnLock()) { |
| 6914 | serverAssert(c->flags & CLIENT_PROTECTED || c->flags & CLIENT_EXECUTING_COMMAND); // If the client is not protected we have no gurantee they won't be free'd in the event loop |
| 6915 | c->lock.unlock(); |
| 6916 | vecclients.push_back(c); |
| 6917 | } |
| 6918 | } |
| 6919 | |
| 6920 | /* Since we're about to release our lock we need to flush the repl backlog queue */ |
| 6921 | bool fReplBacklog = g_pserver->repl_batch_offStart >= 0; |
| 6922 | if (fReplBacklog) { |
| 6923 | flushReplBacklogToClients(); |
| 6924 | g_pserver->repl_batch_idxStart = -1; |
| 6925 | g_pserver->repl_batch_offStart = -1; |
| 6926 | } |
| 6927 | |
| 6928 | aeReleaseLock(); |
| 6929 | serverAssert(!GlobalLocksAcquired()); |
| 6930 | try { |
| 6931 | func(); |
| 6932 | } |
| 6933 | catch (...) { |
| 6934 | // Caller expects us to be locked so fix and rethrow |
| 6935 | AeLocker locker; |
| 6936 | locker.arm(nullptr); |
| 6937 | locker.release(); |
| 6938 | for (client *c : vecclients) |
| 6939 | c->lock.lock(); |
| 6940 | throw; |
| 6941 | } |
| 6942 | |
| 6943 | AeLocker locker; |
| 6944 | locker.arm(nullptr); |
| 6945 | locker.release(); |
| 6946 | |
| 6947 | // Restore it so the calling code is not confused |
| 6948 | if (fReplBacklog) { |
| 6949 | g_pserver->repl_batch_idxStart = g_pserver->repl_backlog_idx; |
| 6950 | g_pserver->repl_batch_offStart = g_pserver->master_repl_offset; |
| 6951 | } |
| 6952 | |
| 6953 | for (client *c : vecclients) |
| 6954 | c->lock.lock(); |
| 6955 | } |
| 6956 | |
| 6957 | /* purpose is one of CHILD_TYPE_ types */ |
no test coverage detected