From 76b7233adb5c59b072209434d9a5ee795c5affa5 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 20 Jan 2010 16:57:00 -0500 Subject: [PATCH] fixed a deadlock caused by too much finished processes in queue so that I/O clients writing to the wirte side of the pipe used to awake the main thread where blocking. Then a BGSAVE started waiting for the last active thread to finish, condition impossible because all the I/O threads where blocking on threads. Takes this as a note to myself... --- redis.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/redis.c b/redis.c index 4aacc41b..a7b89b16 100644 --- a/redis.c +++ b/redis.c @@ -7768,6 +7768,8 @@ static void spawnIOThread(void) { * fork() in order to BGSAVE or BGREWRITEAOF. */ static void waitEmptyIOJobsQueue(void) { while(1) { + int io_processed_len; + lockThreadedIO(); if (listLength(server.io_newjobs) == 0 && listLength(server.io_processing) == 0 && @@ -7776,8 +7778,18 @@ static void waitEmptyIOJobsQueue(void) { unlockThreadedIO(); return; } + /* While waiting for empty jobs queue condition we post-process some + * finshed job, as I/O threads may be hanging trying to write against + * the io_ready_pipe_write FD but there are so much pending jobs that + * it's blocking. */ + io_processed_len = listLength(server.io_processed); unlockThreadedIO(); - usleep(10000); /* 10 milliseconds */ + if (io_processed_len) { + vmThreadedIOCompletedJob(NULL,server.io_ready_pipe_read,NULL,0); + usleep(1000); /* 1 millisecond */ + } else { + usleep(10000); /* 10 milliseconds */ + } } } -- 2.47.2