Skip to content

Commit 59d1bcb

Browse files
authored
Merge pull request #129 from doyoubi/fix/SlowlogCrash
Fix slowlog crash when redirection fails
2 parents b9dd3c7 + 115da6c commit 59d1bcb

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

.travis.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ before_install:
77
- sudo apt-get install -qq valgrind
88

99
install:
10+
- wget http://download.redis.io/releases/redis-3.0.7.tar.gz
11+
- tar xzf redis-3.0.7.tar.gz
12+
- cd redis-3.0.7
13+
- make
14+
- sudo cp src/redis-server `which redis-server`
15+
- cd ../
16+
1017
- sudo mkdir -p /etc/redis /var/lib/redis/cluster/{8000,8001,8002,8003}
1118

1219
- sudo chmod -R 777 /etc/redis
@@ -27,8 +34,11 @@ install:
2734
- sudo redis-server /etc/redis/redis-cluster-8001.conf
2835
- sudo redis-server /etc/redis/redis-cluster-8002.conf
2936
- sudo redis-server /etc/redis/redis-cluster-8003.conf
37+
- redis-server -v
3038

39+
- sudo pip install redis==2.10.5
3140
- sudo pip install ruskit
41+
- pip freeze
3242
- ruskit create localhost:800{0,1,2}
3343

3444
- sed -i 's/node localhost:8000,localhost:8001,localhost:8002/node 127.0.0.1:8000/' corvus.conf
@@ -49,7 +59,6 @@ before_script:
4959
- ./src/corvus ./corvus.conf > corvus.log 2>&1 &
5060

5161
script:
52-
- redis-server -v
5362
- awk '/ERROR SUMMARY/ {if ($4 == 0) exit 0; else exit 1}' valgrind.log
5463
- make clean || true
5564
- make test

src/command.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,13 @@ void cmd_mark(struct command *cmd, int fail)
11201120
if (cmd->parent->cmd_done_count == cmd->parent->cmd_count) {
11211121
root = cmd->parent;
11221122
}
1123+
// In some cases cmd->cmd_fail is true though,
1124+
// cmd->parent->cmd_fail is not. But since `cmd_fail`
1125+
// implys a not null `fail_reason` (and maybe some other rules),
1126+
// now we keep it unchanged.
1127+
// if (fail) {
1128+
// cmd->parent->cmd_fail = true;
1129+
// }
11231130
}
11241131

11251132
if (root != NULL && conn_register(root->client) == CORVUS_ERR) {

src/slowlog.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ struct slowlog_entry *slowlog_create_entry(struct command *cmd, int64_t remote_l
111111
return entry;
112112
}
113113

114-
// Return NULL when `cmd` is not a multiple keys command
114+
// Return NULL when `cmd` is not a multiple keys command or fail to connect to redis
115115
struct slowlog_entry *slowlog_create_sub_entry(struct command *cmd, int64_t total_latency)
116116
{
117117
switch (cmd->cmd_type) {
@@ -135,6 +135,12 @@ struct slowlog_entry *slowlog_create_sub_entry(struct command *cmd, int64_t tota
135135
slowest_sub_cmd = c;
136136
}
137137
}
138+
// When corvus fails to redirect commands to redis, the `remote_latency` above
139+
// may become zero or nagative and produce a NULL `slowest_sub_cmd`.
140+
// In this case we just ignore it.
141+
if (NULL == slowest_sub_cmd) {
142+
return NULL;
143+
}
138144
return slowlog_create_entry(slowest_sub_cmd, max_remote_latency / 1000, total_latency);
139145
}
140146

tests/test_slowlog.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,48 @@ TEST(test_slowlog_statsd) {
223223
PASS(NULL);
224224
}
225225

226+
TEST(test_failed_command_slowlog) {
227+
struct mbuf buf;
228+
struct command cmd;
229+
memset(&cmd, 0, sizeof(struct command));
230+
STAILQ_INIT(&cmd.sub_cmds);
231+
232+
struct reader r = {0};
233+
const char cmd_data[] = "*2\r\n$4\r\nMGET\r\n$4\r\nkey1\r\n";
234+
buf.pos = (uint8_t*)cmd_data;
235+
buf.last = (uint8_t*)cmd_data + strlen(cmd_data);
236+
reader_init(&r);
237+
reader_feed(&r, &buf);
238+
ASSERT(parse(&r, MODE_REQ) != -1);
239+
cmd.data = r.data;
240+
cmd.prefix = NULL;
241+
242+
struct command sub_cmd;
243+
sub_cmd.parent = &cmd;
244+
STAILQ_INSERT_TAIL(&cmd.sub_cmds, &sub_cmd, sub_cmd_next);
245+
246+
// When corvus fails to redirect command, these two fields may be zero.
247+
cmd.rep_time[0] = 0;
248+
cmd.rep_time[1] = 0;
249+
sub_cmd.rep_time[0] = 0;
250+
sub_cmd.rep_time[1] = 0;
251+
252+
struct slowlog_entry *entry = slowlog_create_entry(&cmd, 0, 666233);
253+
ASSERT(entry->remote_latency == 0);
254+
ASSERT(entry->total_latency == 666233);
255+
slowlog_dec_ref(entry);
256+
entry = slowlog_create_sub_entry(&cmd, 666233);
257+
ASSERT(NULL == entry);
258+
259+
redis_data_free(&cmd.data);
260+
PASS(NULL);
261+
}
262+
226263
TEST_CASE(test_slowlog) {
227264
RUN_TEST(test_slowlog_create_entry);
228265
RUN_TEST(test_slowlog_create_entry_with_prefix);
229266
RUN_TEST(test_slowlog_create_entry_with_long_arg);
230267
RUN_TEST(test_slowlog_statsd);
231268
RUN_TEST(test_entry_get_set);
269+
RUN_TEST(test_failed_command_slowlog);
232270
}

0 commit comments

Comments
 (0)