提交 0d7366c3 编写于 作者: J Jonathan Pickett

workaround for deadlocking on RDB file copy during multiple master/slave synchronizations

上级 8a47dc3c
......@@ -582,7 +582,7 @@ BOOL AbortForkOperation()
BOOL EndForkOperation() {
try {
#ifdef _DEBUG
printf("sending termiation signal\n");
printf("EndForkOperation: sending termination signal\n");
#endif
SetEvent(g_pQForkControl->terminateForkedProcess);
if( g_hForkedProcess != 0 )
......
......@@ -671,8 +671,13 @@ void freeClient(redisClient *c) {
* Case 1: we lost the connection with a slave. */
if (c->flags & REDIS_SLAVE) {
list *l;
if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1)
if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1) {
close(c->repldbfd);
#ifdef _WIN32
DeleteFileA(c->replFileCopy);
memset(c->replFileCopy, 0, MAX_PATH);
#endif
}
l = (c->flags & REDIS_MONITOR) ? server.monitors : server.slaves;
ln = listSearchKey(l,c);
redisAssert(ln != NULL);
......
......@@ -411,6 +411,7 @@ typedef struct redisClient {
int replstate; /* replication state if this is a slave */
int repldbfd; /* replication DB file descriptor */
#ifdef _WIN32
char replFileCopy[_MAX_PATH];
long long repldboff; /* replication DB file offset */
long long repldbsize; /* replication DB file size */
#else
......
......@@ -243,6 +243,10 @@ void sendBulkToSlaveDataDone(aeEventLoop *el, int fd, void *privdata, int nwritt
slave->repldboff += nwritten;
if (slave->repldboff == slave->repldbsize) {
close(slave->repldbfd);
#ifdef _WIN32
DeleteFileA(slave->replFileCopy);
memset(slave->replFileCopy, 0, MAX_PATH);
#endif
slave->repldbfd = -1;
aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);
slave->replstate = REDIS_REPL_ONLINE;
......@@ -343,6 +347,10 @@ void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {
slave->repldboff += nwritten;
if (slave->repldboff == slave->repldbsize) {
close(slave->repldbfd);
#ifdef _WIN32
DeleteFileA(slave->replFileCopy);
memset(slave->replFileCopy, 0, MAX_PATH);
#endif
slave->repldbfd = -1;
aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE);
slave->replstate = REDIS_REPL_ONLINE;
......@@ -383,7 +391,20 @@ void updateSlavesWaitingBgsave(int bgsaveerr) {
continue;
}
#ifdef _WIN32
if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY|_O_BINARY,0)) == -1 ||
/* As multiple slaves join asynchronously with the master, the synchronization process can launch multiple
RDB background saves before the first slaves are fully synchronized. This can cause a race condition
for the RDB file produced by the forked process with the RDB file being used to feed the slaves.
I don't think this patch totally eliminates the race condition, but it does eliminate the deadlock
that occurs when the forked process tries to copy the file it produces over the the RDB file being
held open by the slave feeding code. */
sprintf(slave->replFileCopy,"%d_%s", slave->fd, server.rdb_filename);
if(CopyFileA( server.rdb_filename, slave->replFileCopy, FALSE) == FALSE) {
freeClient(slave);
redisLog(REDIS_WARNING,"Failed to duplicate RDB file. Failing SYNC: %d", GetLastError());
continue;
}
if ((slave->repldbfd = open(slave->replFileCopy,O_RDONLY|_O_BINARY,0)) == -1 ||
#else
if ((slave->repldbfd = open(server.rdb_filename,O_RDONLY)) == -1 ||
#endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册