summaryrefslogtreecommitdiffstats
path: root/tests/omprog-restart-terminated.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xtests/omprog-restart-terminated.sh155
1 files changed, 155 insertions, 0 deletions
diff --git a/tests/omprog-restart-terminated.sh b/tests/omprog-restart-terminated.sh
new file mode 100755
index 0000000..8fbc99e
--- /dev/null
+++ b/tests/omprog-restart-terminated.sh
@@ -0,0 +1,155 @@
+#!/bin/bash
+# This file is part of the rsyslog project, released under ASL 2.0
+
+# This test checks that omprog restarts the external program when it
+# terminates prematurely, and that it does so without leaking file
+# descriptors. Two cases are checked: termination of the program when
+# omprog is going to write to the pipe (to send a message to the
+# program), and when omprog is going to read from the pipe (when it
+# is expecting the program to confirm the last message).
+
+. ${srcdir:=.}/diag.sh init
+check_command_available lsof
+
+generate_conf
+add_conf '
+module(load="../plugins/omprog/.libs/omprog")
+
+template(name="outfmt" type="string" string="%msg%\n")
+
+:msg, contains, "msgnum:" {
+ action(
+ type="omprog"
+ binary="'$RSYSLOG_DYNNAME'.omprog-restart-terminated-bin.sh"
+ template="outfmt"
+ name="omprog_action"
+ queue.type="Direct" # the default; facilitates sync with the child process
+ confirmMessages="on" # facilitates sync with the child process
+ action.resumeRetryCount="3"
+ action.resumeInterval="1"
+ action.reportSuspensionContinuation="on"
+ signalOnClose="off"
+ )
+}
+
+syslog.* {
+ action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG`)
+}
+'
+
+# We need a test-specific program name, as the test needs to signal the child process
+cp -f $srcdir/testsuites/omprog-restart-terminated-bin.sh $RSYSLOG_DYNNAME.omprog-restart-terminated-bin.sh
+
+# On Solaris 10, the output of ps is truncated for long process names; use /usr/ucb/ps instead:
+if [[ $(uname) = "SunOS" && $(uname -r) = "5.10" ]]; then
+ function get_child_pid {
+ /usr/ucb/ps -awwx | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $1 }'
+ }
+else
+ function get_child_pid {
+ ps -ef | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $2 }'
+ }
+fi
+
+startup
+injectmsg 0 1
+wait_queueempty
+
+pid=$(getpid)
+echo PID: $pid
+start_fd_count=$(lsof -p $pid | wc -l)
+
+injectmsg 1 1
+injectmsg 2 1
+wait_queueempty
+
+child_pid_1=$(get_child_pid)
+kill -s USR1 $child_pid_1
+./msleep 100
+
+injectmsg 3 1
+injectmsg 4 1
+wait_queueempty
+
+child_pid_2=$(get_child_pid)
+kill -s TERM $child_pid_2
+./msleep 100
+
+injectmsg 5 1
+injectmsg 6 1
+injectmsg 7 1
+wait_queueempty
+
+child_pid_3=$(get_child_pid)
+kill -s KILL $child_pid_3
+./msleep 100
+
+injectmsg 8 1
+injectmsg 9 1
+wait_queueempty
+
+end_fd_count=$(lsof -p $pid | wc -l)
+child_pid_4=$(get_child_pid)
+child_lsof=$(lsof -a -d 0-65535 -p $child_pid_4 | awk '$4 != "255r" { print $4 " " $9 }')
+
+shutdown_when_empty
+wait_shutdown
+
+export EXPECTED="Starting
+Received msgnum:00000000:
+Received msgnum:00000001:
+Received msgnum:00000002:
+Received SIGUSR1, will terminate after the next message
+Received msgnum:00000003:
+Terminating without confirming the last message
+Starting
+Received msgnum:00000003:
+Received msgnum:00000004:
+Received SIGTERM, terminating
+Starting
+Received msgnum:00000005:
+Received msgnum:00000006:
+Received msgnum:00000007:
+Starting
+Received msgnum:00000008:
+Received msgnum:00000009:
+Terminating normally"
+cmp_exact $RSYSLOG_OUT_LOG
+
+if [[ "$start_fd_count" != "$end_fd_count" ]]; then
+ echo "file descriptor leak: started with $start_fd_count open files, ended with $end_fd_count"
+ error_exit 1
+fi
+
+# Check that the child process does not inherit open fds from rsyslog
+# (apart from the pipes), and that stderr is redirected to /dev/null.
+# Ignore fd 255, which bash opens for internal use.
+
+EXPECTED_CHILD_LSOF="FD NAME
+0r pipe
+1w pipe
+2w /dev/null"
+
+# On Solaris, lsof gives this alternate output:
+EXPECTED_CHILD_LSOF_2="FD NAME
+0u (fifofs)
+1u (fifofs)
+2w "
+
+if [[ "$child_lsof" != "$EXPECTED_CHILD_LSOF" && "$child_lsof" != "$EXPECTED_CHILD_LSOF_2" ]]; then
+ echo "unexpected open files for child process:"
+ echo "$child_lsof"
+ error_exit 1
+fi
+
+# Check also that child process terminations are reported correctly.
+# When the reportChildProcessExits global parameter is "errors" (the default),
+# only non-zero exit codes are reported.
+content_check "(pid $child_pid_1) terminated; will be restarted" $RSYSLOG2_OUT_LOG
+custom_assert_content_missing "(pid $child_pid_1) exited with status" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_2) terminated; will be restarted" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_2) exited with status 1" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_3) terminated; will be restarted" $RSYSLOG2_OUT_LOG
+content_check "(pid $child_pid_3) terminated by signal 9" $RSYSLOG2_OUT_LOG
+
+exit_test