summaryrefslogtreecommitdiffstats
path: root/tests/omprog-restart-terminated.sh
blob: 8fbc99e217453793ede6275a21003ed7325aff48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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