Skip to content

Commit 0b7b533

Browse files
committed
Merge branch 'unstable' into RELEASE_6
2 parents d30fcfb + 165333b commit 0b7b533

File tree

8 files changed

+61
-99
lines changed

8 files changed

+61
-99
lines changed

src/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ endif
4848
USEASM?=true
4949

5050
ifneq ($(strip $(SANITIZE)),)
51-
CFLAGS+= -fsanitize=$(SANITIZE) -DSANITIZE
52-
CXXFLAGS+= -fsanitize=$(SANITIZE) -DSANITIZE
51+
CFLAGS+= -fsanitize=$(SANITIZE) -DSANITIZE -fno-omit-frame-pointer
52+
CXXFLAGS+= -fsanitize=$(SANITIZE) -DSANITIZE -fno-omit-frame-pointer
5353
LDFLAGS+= -fsanitize=$(SANITIZE)
5454
MALLOC=libc
5555
USEASM=false

src/ae.cpp

Lines changed: 5 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,6 @@ enum class AE_ASYNC_OP
109109
CreateFileEvent,
110110
};
111111

112-
struct aeCommandControl
113-
{
114-
std::condition_variable cv;
115-
std::atomic<int> rval;
116-
std::mutex mutexcv;
117-
};
118-
119112
struct aeCommand
120113
{
121114
AE_ASYNC_OP op;
@@ -128,7 +121,6 @@ struct aeCommand
128121
std::function<void()> *pfn;
129122
};
130123
void *clientData;
131-
aeCommandControl *pctl;
132124
};
133125

134126
void aeProcessCmd(aeEventLoop *eventLoop, int fd, void *, int )
@@ -149,19 +141,7 @@ void aeProcessCmd(aeEventLoop *eventLoop, int fd, void *, int )
149141
break;
150142

151143
case AE_ASYNC_OP::CreateFileEvent:
152-
{
153-
if (cmd.pctl != nullptr)
154-
{
155-
cmd.pctl->mutexcv.lock();
156-
std::atomic_store(&cmd.pctl->rval, aeCreateFileEvent(eventLoop, cmd.fd, cmd.mask, cmd.fproc, cmd.clientData));
157-
cmd.pctl->cv.notify_all();
158-
cmd.pctl->mutexcv.unlock();
159-
}
160-
else
161-
{
162-
aeCreateFileEvent(eventLoop, cmd.fd, cmd.mask, cmd.fproc, cmd.clientData);
163-
}
164-
}
144+
aeCreateFileEvent(eventLoop, cmd.fd, cmd.mask, cmd.fproc, cmd.clientData);
165145
break;
166146

167147
case AE_ASYNC_OP::PostFunction:
@@ -175,19 +155,11 @@ void aeProcessCmd(aeEventLoop *eventLoop, int fd, void *, int )
175155

176156
case AE_ASYNC_OP::PostCppFunction:
177157
{
178-
if (cmd.pctl != nullptr)
179-
cmd.pctl->mutexcv.lock();
180-
181158
std::unique_lock<decltype(g_lock)> ulock(g_lock, std::defer_lock);
182159
if (cmd.fLock)
183160
ulock.lock();
184161
(*cmd.pfn)();
185-
186-
if (cmd.pctl != nullptr)
187-
{
188-
cmd.pctl->cv.notify_all();
189-
cmd.pctl->mutexcv.unlock();
190-
}
162+
191163
delete cmd.pfn;
192164
}
193165
break;
@@ -226,7 +198,7 @@ ssize_t safe_write(int fd, const void *pv, size_t cb)
226198
}
227199

228200
int aeCreateRemoteFileEvent(aeEventLoop *eventLoop, int fd, int mask,
229-
aeFileProc *proc, void *clientData, int fSynchronous)
201+
aeFileProc *proc, void *clientData)
230202
{
231203
if (eventLoop == g_eventLoopThisThread)
232204
return aeCreateFileEvent(eventLoop, fd, mask, proc, clientData);
@@ -239,13 +211,7 @@ int aeCreateRemoteFileEvent(aeEventLoop *eventLoop, int fd, int mask,
239211
cmd.mask = mask;
240212
cmd.fproc = proc;
241213
cmd.clientData = clientData;
242-
cmd.pctl = nullptr;
243214
cmd.fLock = true;
244-
if (fSynchronous)
245-
{
246-
cmd.pctl = new (MALLOC_LOCAL) aeCommandControl();
247-
cmd.pctl->mutexcv.lock();
248-
}
249215

250216
auto size = safe_write(eventLoop->fdCmdWrite, &cmd, sizeof(cmd));
251217
if (size != sizeof(cmd))
@@ -254,16 +220,6 @@ int aeCreateRemoteFileEvent(aeEventLoop *eventLoop, int fd, int mask,
254220
serverAssert(errno == EAGAIN);
255221
ret = AE_ERR;
256222
}
257-
258-
if (fSynchronous)
259-
{
260-
{
261-
std::unique_lock<std::mutex> ulock(cmd.pctl->mutexcv, std::adopt_lock);
262-
cmd.pctl->cv.wait(ulock);
263-
ret = cmd.pctl->rval;
264-
}
265-
delete cmd.pctl;
266-
}
267223

268224
return ret;
269225
}
@@ -286,7 +242,7 @@ int aePostFunction(aeEventLoop *eventLoop, aePostFunctionProc *proc, void *arg)
286242
return AE_OK;
287243
}
288244

289-
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fSynchronous, bool fLock, bool fForceQueue)
245+
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fLock, bool fForceQueue)
290246
{
291247
if (eventLoop == g_eventLoopThisThread && !fForceQueue)
292248
{
@@ -297,13 +253,7 @@ int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fSynch
297253
aeCommand cmd = {};
298254
cmd.op = AE_ASYNC_OP::PostCppFunction;
299255
cmd.pfn = new (MALLOC_LOCAL) std::function<void()>(fn);
300-
cmd.pctl = nullptr;
301256
cmd.fLock = fLock;
302-
if (fSynchronous)
303-
{
304-
cmd.pctl = new (MALLOC_LOCAL) aeCommandControl;
305-
cmd.pctl->mutexcv.lock();
306-
}
307257

308258
auto size = write(eventLoop->fdCmdWrite, &cmd, sizeof(cmd));
309259
if (!(!size || size == sizeof(cmd))) {
@@ -314,17 +264,7 @@ int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fSynch
314264
if (size == 0)
315265
return AE_ERR;
316266

317-
int ret = AE_OK;
318-
if (fSynchronous)
319-
{
320-
{
321-
std::unique_lock<std::mutex> ulock(cmd.pctl->mutexcv, std::adopt_lock);
322-
cmd.pctl->cv.wait(ulock);
323-
ret = cmd.pctl->rval;
324-
}
325-
delete cmd.pctl;
326-
}
327-
return ret;
267+
return AE_OK;
328268
}
329269

330270
aeEventLoop *aeCreateEventLoop(int setsize) {

src/ae.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ aeEventLoop *aeCreateEventLoop(int setsize);
135135
int aePostFunction(aeEventLoop *eventLoop, aePostFunctionProc *proc, void *arg);
136136
#ifdef __cplusplus
137137
} // EXTERN C
138-
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fSynchronous = false, bool fLock = true, bool fForceQueue = false);
138+
int aePostFunction(aeEventLoop *eventLoop, std::function<void()> fn, bool fLock = true, bool fForceQueue = false);
139139
extern "C" {
140140
#endif
141141
void aeDeleteEventLoop(aeEventLoop *eventLoop);
@@ -144,7 +144,7 @@ int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
144144
aeFileProc *proc, void *clientData);
145145

146146
int aeCreateRemoteFileEvent(aeEventLoop *eventLoop, int fd, int mask,
147-
aeFileProc *proc, void *clientData, int fSynchronous);
147+
aeFileProc *proc, void *clientData);
148148

149149
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
150150
void aeDeleteFileEventAsync(aeEventLoop *eventLoop, int fd, int mask);

src/cluster.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5066,12 +5066,15 @@ void mvccrestoreCommand(client *c) {
50665066
setMvccTstamp(obj, mvcc);
50675067

50685068
/* Create the key and set the TTL if any */
5069-
dbMerge(c->db,key,obj,true);
5070-
if (expire >= 0) {
5071-
setExpire(c,c->db,key,nullptr,expire);
5069+
if (dbMerge(c->db,key,obj,true)) {
5070+
if (expire >= 0) {
5071+
setExpire(c,c->db,key,nullptr,expire);
5072+
}
5073+
signalModifiedKey(c,c->db,key);
5074+
notifyKeyspaceEvent(NOTIFY_GENERIC,"restore",key,c->db->id);
5075+
} else {
5076+
decrRefCount(obj);
50725077
}
5073-
signalModifiedKey(c,c->db,key);
5074-
notifyKeyspaceEvent(NOTIFY_GENERIC,"restore",key,c->db->id);
50755078
addReply(c,shared.ok);
50765079
g_pserver->dirty++;
50775080
}

src/expire.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ void activeExpireCycleExpire(redisDb *db, expireEntry &e, long long now) {
136136
executeCronJobExpireHook(keyCopy, val);
137137
sdsfree(keyCopy);
138138
decrRefCount(val);
139-
}, false, true /*fLock*/, true /*fForceQueue*/);
139+
}, true /*fLock*/, true /*fForceQueue*/);
140140
}
141141
return;
142142

src/module.cpp

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5045,7 +5045,7 @@ void RM_FreeThreadSafeContext(RedisModuleCtx *ctx) {
50455045
zfree(ctx);
50465046
}
50475047

5048-
static bool g_fModuleThread = false;
5048+
thread_local bool g_fModuleThread = false;
50495049
/* Acquire the server lock before executing a thread safe API call.
50505050
* This is not needed for `RedisModule_Reply*` calls when there is
50515051
* a blocked client connected to the thread safe context. */
@@ -5104,7 +5104,14 @@ void moduleAcquireGIL(int fServerThread) {
51045104
}
51055105
else
51065106
{
5107-
s_mutexModule.lock();
5107+
// It is possible that another module thread holds the GIL (and s_mutexModule as a result).
5108+
// When said thread goes to release the GIL, it will wait for s_mutex, which this thread owns.
5109+
// This thread is however waiting for the GIL (and s_mutexModule) that the other thread owns.
5110+
// As a result, a deadlock has occured.
5111+
// We release the lock on s_mutex and wait until we are able to safely acquire the GIL
5112+
// in order to prevent this deadlock from occuring.
5113+
while (!s_mutexModule.try_lock())
5114+
s_cv.wait(lock);
51085115
++s_cAcquisitionsModule;
51095116
fModuleGILWlocked++;
51105117
}
@@ -5643,6 +5650,9 @@ int moduleTimerHandler(struct aeEventLoop *eventLoop, long long id, void *client
56435650
* (If the time it takes to execute 'callback' is negligible the two
56445651
* statements above mean the same) */
56455652
RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) {
5653+
static uint64_t pending_key;
5654+
static mstime_t pending_period = -1;
5655+
56465656
RedisModuleTimer *timer = (RedisModuleTimer*)zmalloc(sizeof(*timer), MALLOC_LOCAL);
56475657
timer->module = ctx->module;
56485658
timer->callback = callback;
@@ -5661,32 +5671,40 @@ RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisMod
56615671
}
56625672
}
56635673

5674+
bool fNeedPost = (pending_period < 0); // If pending_period is already set, then a PostFunction is in flight and we don't need to set a new one
5675+
if (pending_period < 0 || period < pending_period) {
5676+
pending_period = period;
5677+
pending_key = key;
5678+
}
5679+
56645680
/* We need to install the main event loop timer if it's not already
56655681
* installed, or we may need to refresh its period if we just installed
56665682
* a timer that will expire sooner than any other else (i.e. the timer
56675683
* we just installed is the first timer in the Timers rax). */
5668-
if (aeTimer != -1) {
5669-
raxIterator ri;
5670-
raxStart(&ri,Timers);
5671-
raxSeek(&ri,"^",NULL,0);
5672-
raxNext(&ri);
5673-
if (memcmp(ri.key,&key,sizeof(key)) == 0) {
5674-
/* This is the first key, we need to re-install the timer according
5675-
* to the just added event. */
5676-
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, [&]{
5677-
aeDeleteTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,aeTimer);
5678-
}, true /* synchronous */, false /* fLock */);
5679-
aeTimer = -1;
5680-
}
5681-
raxStop(&ri);
5682-
}
5684+
if (fNeedPost) {
5685+
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, []{
5686+
if (aeTimer != -1) {
5687+
raxIterator ri;
5688+
raxStart(&ri,Timers);
5689+
raxSeek(&ri,"^",NULL,0);
5690+
raxNext(&ri);
5691+
if (memcmp(ri.key,&pending_key,sizeof(key)) == 0) {
5692+
/* This is the first key, we need to re-install the timer according
5693+
* to the just added event. */
5694+
aeDeleteTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,aeTimer);
5695+
aeTimer = -1;
5696+
}
5697+
raxStop(&ri);
5698+
}
5699+
5700+
/* If we have no main timer (the old one was invalidated, or this is the
5701+
* first module timer we have), install one. */
5702+
if (aeTimer == -1) {
5703+
aeTimer = aeCreateTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,pending_period,moduleTimerHandler,NULL,NULL);
5704+
}
56835705

5684-
/* If we have no main timer (the old one was invalidated, or this is the
5685-
* first module timer we have), install one. */
5686-
if (aeTimer == -1) {
5687-
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, [&]{
5688-
aeTimer = aeCreateTimeEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el,period,moduleTimerHandler,NULL,NULL);
5689-
}, true /* synchronous */, false /* fLock */);
5706+
pending_period = -1;
5707+
});
56905708
}
56915709

56925710
return key;

src/server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4087,7 +4087,7 @@ bool client::postFunction(std::function<void(client *)> fn, bool fLock) {
40874087
std::lock_guard<decltype(this->lock)> lock(this->lock);
40884088
fn(this);
40894089
--casyncOpsPending;
4090-
}, false, fLock) == AE_OK;
4090+
}, fLock) == AE_OK;
40914091
}
40924092

40934093
/*================================== Shutdown =============================== */

tests/unit/moduleapi/hooks.tcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ tags "modules" {
132132
}
133133

134134
$replica replicaof no one
135+
after 300
135136

136137
test {Test role-master hook} {
137138
assert_equal [r hooks.event_count role-replica] 1

0 commit comments

Comments
 (0)