summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAndy Pan <panjf2000@gmail.com>2021-01-20 04:57:30 +0800
committerGitHub <noreply@github.com>2021-01-19 22:57:30 +0200
commitfb66e2e24943018961321d13e46ee2ab66de882a (patch)
tree04075a8d909bc1eba249ecb1aaf1b4705fc84823 /tests
parentaaf71b380ed5ef8d5d63f8a60733c35202c5b838 (diff)
downloadredis-fb66e2e24943018961321d13e46ee2ab66de882a.tar.gz
Use FD_CLOEXEC in Sentinel, so that FDs don't leak to the scripts it runs (#8242)
Sentinel uses execve to run scripts, so it needs to use FD_CLOEXEC on all file descriptors, so that they're not accessible by the script it runs. This commit includes a change to the sentinel tests, which verifies no FDs are left opened when the script is executed.
Diffstat (limited to 'tests')
-rw-r--r--tests/instances.tcl14
-rw-r--r--tests/sentinel/run.tcl2
-rw-r--r--tests/sentinel/tests/includes/init-tests.tcl2
-rwxr-xr-xtests/sentinel/tests/includes/notify.sh20
4 files changed, 36 insertions, 2 deletions
diff --git a/tests/instances.tcl b/tests/instances.tcl
index 18eb1a402..5b25bcc97 100644
--- a/tests/instances.tcl
+++ b/tests/instances.tcl
@@ -400,6 +400,11 @@ proc check_leaks instance_types {
# Execute all the units inside the 'tests' directory.
proc run_tests {} {
+ set sentinel_fd_leaks_file "sentinel_fd_leaks"
+ if { [file exists $sentinel_fd_leaks_file] } {
+ file delete $sentinel_fd_leaks_file
+ }
+
set tests [lsort [glob ../tests/*]]
foreach test $tests {
if {$::run_matching ne {} && [string match $::run_matching $test] == 0} {
@@ -414,7 +419,14 @@ proc run_tests {} {
# Print a message and exists with 0 / 1 according to zero or more failures.
proc end_tests {} {
- if {$::failed == 0} {
+ set sentinel_fd_leaks_file "sentinel_fd_leaks"
+ if { [file exists $sentinel_fd_leaks_file] } {
+ puts [colorstr red "WARNING: sentinel test(s) failed, there are leaked fds in sentinel:"]
+ exec cat $sentinel_fd_leaks_file
+ exit 1
+ }
+
+ if {$::failed == 0 } {
puts "GOOD! No errors."
exit 0
} else {
diff --git a/tests/sentinel/run.tcl b/tests/sentinel/run.tcl
index 996af906a..99362c193 100644
--- a/tests/sentinel/run.tcl
+++ b/tests/sentinel/run.tcl
@@ -10,7 +10,7 @@ set ::tlsdir "../../tls"
proc main {} {
parse_options
- spawn_instance sentinel $::sentinel_base_port $::instances_count
+ spawn_instance sentinel $::sentinel_base_port $::instances_count [list "sentinel deny-scripts-reconfig no"]
spawn_instance redis $::redis_base_port $::instances_count
run_tests
cleanup
diff --git a/tests/sentinel/tests/includes/init-tests.tcl b/tests/sentinel/tests/includes/init-tests.tcl
index 234f9c589..d6796fda6 100644
--- a/tests/sentinel/tests/includes/init-tests.tcl
+++ b/tests/sentinel/tests/includes/init-tests.tcl
@@ -37,6 +37,8 @@ test "(init) Sentinels can start monitoring a master" {
S $id SENTINEL SET mymaster down-after-milliseconds 2000
S $id SENTINEL SET mymaster failover-timeout 20000
S $id SENTINEL SET mymaster parallel-syncs 10
+ S $id SENTINEL SET mymaster notification-script ../../tests/includes/notify.sh
+ S $id SENTINEL SET mymaster client-reconfig-script ../../tests/includes/notify.sh
}
}
diff --git a/tests/sentinel/tests/includes/notify.sh b/tests/sentinel/tests/includes/notify.sh
new file mode 100755
index 000000000..09a8addca
--- /dev/null
+++ b/tests/sentinel/tests/includes/notify.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+OS=`uname -s`
+if [ ${OS} == "Linux" ]
+then
+ exit 0
+fi
+
+# fd 3 is meant to catch the actual access to /proc/pid/fd,
+# in case there's an fd leak by the sentinel,
+# it can take 3, but then the access to /proc will take another fd, and we'll catch that.
+leaked_fd_count=`ls /proc/self/fd | grep -vE '^[0|1|2|3]$' | wc -l`
+if [ $leaked_fd_count -gt 0 ]
+then
+ sentinel_fd_leaks_file="../sentinel_fd_leaks"
+ if [ ! -f $sentinel_fd_leaks_file ]
+ then
+ ls -l /proc/self/fd | cat >> $sentinel_fd_leaks_file
+ fi
+fi