pcp/SOURCES/redhat-bugzilla-1849511.patch

997 lines
30 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

BZ 1849511 - resolve covscan and other issues from upstream QA 
f7f1dd546 pmproxy: complete handling of HTTP/1.1 TRACE requests
cc662872b qa: add pcp-free-tera archive to pcp-testsuite package
80639d05b pmlogger_check.sh: major overhaul (diags and systemd fixups)
460b7ac2a src/pmlogger/rc_pmlogger: use --quick to pmlogger_check
0b3b4d4ee src/pmlogger/pmlogger_check.service.in: add --skip-primary arg to pmlogger_check
3a68366a8 src/pmlogger/pmlogger.service.in: change ancillary services from After to Before
5d65a6035 src/pmlogger/pmlogger_daily.sh: similar changes to pmlogger_check.sh
ace576907 src/pmlogger/pmlogger_check.sh: fix locking snarfoo
2b2c3db11 src/pmlogger/pmlogger_daily.sh: fix diagnostic spaghetti
4cc54287f pmproxy: allow URLs up to 8k in length
diff -auNr pcp-5.1.1-004/man/man1/pmlogger_check.1 pcp-5.1.1-005/man/man1/pmlogger_check.1
--- pcp-5.1.1-004/man/man1/pmlogger_check.1 2020-04-07 13:31:03.000000000 +1000
+++ pcp-5.1.1-005/man/man1/pmlogger_check.1 2020-06-22 20:08:18.454403788 +1000
@@ -19,7 +19,7 @@
\f3pmlogger_daily\f1 \- administration of Performance Co-Pilot archive log files
.SH SYNOPSIS
.B $PCP_BINADM_DIR/pmlogger_check
-[\f3\-CNsTV?\f1]
+[\f3\-CNpqsTV?\f1]
[\f3\-c\f1 \f2control\f1]
[\f3\-l\f1 \f2logfile\f1]
.br
@@ -269,6 +269,20 @@
.TP
\fB\-p\fR
If this option is specified for
+.B pmlogger_check
+then any line from the control files for the
+.I primary
+.B pmlogger
+will be ignored.
+This option is intended for environments where some system daemon,
+like
+.BR systemd (1),
+is responsible for controlling (starting, stopping, restarting, etc.) the
+.I primary
+.BR pmlogger .
+.TP
+\fB\-p\fR
+If this option is specified for
.B pmlogger_daily
then the status of the daily processing is polled and if the daily
.BR pmlogger (1)
@@ -296,6 +310,12 @@
.B pmlogger_daily
are mutually exclusive.
.TP
+\fB\-q\fR
+If this option is specified for
+.B pmlogger_check
+then the script will ``quickstart'' avoiding any optional processing
+like file compression.
+.TP
\fB\-r\fR, \fB\-\-norewrite\fR
This command line option acts as an override and prevents all archive
rewriting with
diff -auNr pcp-5.1.1-004/qa/1837 pcp-5.1.1-005/qa/1837
--- pcp-5.1.1-004/qa/1837 2020-06-22 20:00:17.636331169 +1000
+++ pcp-5.1.1-005/qa/1837 2020-06-22 20:08:18.457403819 +1000
@@ -1,6 +1,6 @@
#!/bin/sh
# PCP QA Test No. 1837
-# Exercise PMWEBAPI handling server OPTIONS.
+# Exercise PMWEBAPI handling server OPTIONS and TRACE.
#
# Copyright (c) 2020 Red Hat. All Rights Reserved.
#
@@ -43,7 +43,12 @@
# real QA test starts here
_service pmproxy restart >/dev/null 2>&1
-curl -isS --request-target "*" -X OPTIONS http://localhost:44322 \
+echo; echo "=== OPTIONS"
+curl -isS -X OPTIONS --request-target "*" http://localhost:44322 \
+ 2>&1 | tee -a $here/$seq.full | _webapi_header_filter
+
+echo; echo "=== TRACE"
+curl -isS -X TRACE http://localhost:44322 \
2>&1 | tee -a $here/$seq.full | _webapi_header_filter
echo >>$here/$seq.full
diff -auNr pcp-5.1.1-004/qa/1837.out pcp-5.1.1-005/qa/1837.out
--- pcp-5.1.1-004/qa/1837.out 2020-06-22 20:00:17.637331179 +1000
+++ pcp-5.1.1-005/qa/1837.out 2020-06-22 20:08:18.457403819 +1000
@@ -1,6 +1,17 @@
QA output created by 1837
+=== OPTIONS
+
Access-Control-Allow-Methods: GET, PUT, HEAD, POST, TRACE, OPTIONS
Content-Length: 0
Date: DATE
HTTP/1.1 200 OK
+
+=== TRACE
+
+Accept: */*
+Content-Length: 0
+Date: DATE
+HTTP/1.1 200 OK
+Host: localhost:44322
+User-Agent: curl VERSION
diff -auNr pcp-5.1.1-004/qa/archives/GNUmakefile pcp-5.1.1-005/qa/archives/GNUmakefile
--- pcp-5.1.1-004/qa/archives/GNUmakefile 2020-03-19 15:15:42.000000000 +1100
+++ pcp-5.1.1-005/qa/archives/GNUmakefile 2020-06-22 20:08:18.461403861 +1000
@@ -35,6 +35,7 @@
pcp-atop.0.xz pcp-atop.meta pcp-atop.index \
pcp-atop-boot.0.xz pcp-atop-boot.meta pcp-atop-boot.index \
pcp-dstat.0.xz pcp-dstat.meta pcp-dstat.index \
+ pcp-free-tera.0.xz pcp-free-tera.meta.xz pcp-free-tera.index \
pcp-hotatop.0.xz pcp-hotatop.meta pcp-hotatop.index \
pcp-zeroconf.0.xz pcp-zeroconf.meta pcp-zeroconf.index \
value-test.0.xz value-test.meta value-test.index \
diff -auNr pcp-5.1.1-004/qa/common.check pcp-5.1.1-005/qa/common.check
--- pcp-5.1.1-004/qa/common.check 2020-06-22 20:00:17.637331179 +1000
+++ pcp-5.1.1-005/qa/common.check 2020-06-22 20:08:18.459403840 +1000
@@ -2697,6 +2697,7 @@
| col -b \
| sed \
-e 's/^\(Content-Length:\) [1-9][0-9]*/\1 SIZE/g' \
+ -e 's/^\(User-Agent: curl\).*/\1 VERSION/g' \
-e 's/^\(Date:\).*/\1 DATE/g' \
-e 's/\(\"context\":\) [0-9][0-9]*/\1 CTXID/g' \
-e '/^Connection: Keep-Alive/d' \
diff -auNr pcp-5.1.1-004/src/pmlogger/pmlogger_check.service.in pcp-5.1.1-005/src/pmlogger/pmlogger_check.service.in
--- pcp-5.1.1-004/src/pmlogger/pmlogger_check.service.in 2020-05-22 16:40:09.000000000 +1000
+++ pcp-5.1.1-005/src/pmlogger/pmlogger_check.service.in 2020-06-22 20:08:18.452403767 +1000
@@ -6,7 +6,7 @@
[Service]
Type=oneshot
TimeoutStartSec=25m
-Environment="PMLOGGER_CHECK_PARAMS=-C"
+Environment="PMLOGGER_CHECK_PARAMS=-C --skip-primary"
EnvironmentFile=-@PCP_SYSCONFIG_DIR@/pmlogger_timers
ExecStart=@PCP_BINADM_DIR@/pmlogger_check $PMLOGGER_CHECK_PARAMS
WorkingDirectory=@PCP_VAR_DIR@
diff -auNr pcp-5.1.1-004/src/pmlogger/pmlogger_check.sh pcp-5.1.1-005/src/pmlogger/pmlogger_check.sh
--- pcp-5.1.1-004/src/pmlogger/pmlogger_check.sh 2020-05-04 09:52:04.000000000 +1000
+++ pcp-5.1.1-005/src/pmlogger/pmlogger_check.sh 2020-06-22 20:13:04.029416598 +1000
@@ -36,16 +36,24 @@
echo >$tmp/lock
prog=`basename $0`
PROGLOG=$PCP_LOG_DIR/pmlogger/$prog.log
+MYPROGLOG=$PROGLOG.$$
USE_SYSLOG=true
_cleanup()
{
+ if [ -s "$MYPROGLOG" ]
+ then
+ rm -f "$PROGLOG"
+ mv "$MYPROGLOG" "$PROGLOG"
+ else
+ rm -f "$MYPROGLOG"
+ fi
$USE_SYSLOG && [ $status -ne 0 ] && \
$PCP_SYSLOG_PROG -p daemon.error "$prog failed - see $PROGLOG"
- [ -s "$PROGLOG" ] || rm -f "$PROGLOG"
lockfile=`cat $tmp/lock 2>/dev/null`
rm -f "$lockfile"
rm -rf $tmp
+ $VERY_VERBOSE && echo "End: `date '+%F %T.%N'`"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -86,6 +94,8 @@
CHECK_RUNLEVEL=false
START_PMLOGGER=true
STOP_PMLOGGER=false
+QUICKSTART=false
+SKIP_PRIMARY=false
echo > $tmp/usage
cat >> $tmp/usage << EOF
@@ -94,6 +104,8 @@
-l=FILE,--logfile=FILE send important diagnostic messages to FILE
-C query system service runlevel information
-N,--showme perform a dry run, showing what would be done
+ -p,--skip-primary do not start or stop the primary pmlogger instance
+ -q,--quick quick start, no compression
-s,--stop stop pmlogger processes instead of starting them
-T,--terse produce a terser form of output
-V,--verbose increase diagnostic verbosity
@@ -117,6 +129,7 @@
-C) CHECK_RUNLEVEL=true
;;
-l) PROGLOG="$2"
+ MYPROGLOG="$PROGLOG".$$
USE_SYSLOG=false
daily_args="${daily_args} -l $2.from.check"
shift
@@ -129,6 +142,10 @@
KILL="echo + kill"
daily_args="${daily_args} -N"
;;
+ -p) SKIP_PRIMARY=true
+ ;;
+ -q) QUICKSTART=true
+ ;;
-s) START_PMLOGGER=false
STOP_PMLOGGER=true
;;
@@ -162,9 +179,15 @@
_compress_now()
{
- # If $PCP_COMPRESSAFTER=0 in the control file(s), compress archives now.
- # Invoked just before exit when this script has finished successfully.
- $PCP_BINADM_DIR/pmlogger_daily -K $daily_args
+ if $QUICKSTART
+ then
+ $VERY_VERBOSE && echo "Skip compression, -q/--quick on command line"
+ else
+ # If $PCP_COMPRESSAFTER=0 in the control file(s), compress archives now.
+ # Invoked just before exit when this script has finished successfully.
+ $VERY_VERBOSE && echo "Doing compression ..."
+ $PCP_BINADM_DIR/pmlogger_daily -K $daily_args
+ fi
}
# after argument checking, everything must be logged to ensure no mail is
@@ -187,26 +210,37 @@
#
# Exception ($SHOWME, above) is for -N where we want to see the output.
#
- touch "$PROGLOG"
- chown $PCP_USER:$PCP_GROUP "$PROGLOG" >/dev/null 2>&1
- exec 1>"$PROGLOG" 2>&1
+ touch "$MYPROGLOG"
+ chown $PCP_USER:$PCP_GROUP "$MYPROGLOG" >/dev/null 2>&1
+ exec 1>"$MYPROGLOG" 2>&1
+fi
+
+if $VERY_VERBOSE
+then
+ echo "Start: `date '+%F %T.%N'`"
+ if `which pstree >/dev/null 2>&1`
+ then
+ echo "Called from:"
+ pstree -spa $$
+ echo "--- end of pstree output ---"
+ fi
fi
# if SaveLogs exists in the $PCP_LOG_DIR/pmlogger directory then save
-# $PROGLOG there as well with a unique name that contains the date and time
+# $MYPROGLOG there as well with a unique name that contains the date and time
# when we're run
#
if [ -d $PCP_LOG_DIR/pmlogger/SaveLogs ]
then
- now="`date '+%Y%m%d.%H.%M'`"
- link=`echo $PROGLOG | sed -e "s/$prog/SaveLogs\/$prog.$now/"`
+ now="`date '+%Y%m%d.%H.%M.%S'`"
+ link=`echo $MYPROGLOG | sed -e "s/$prog/SaveLogs\/$prog.$now/"`
if [ ! -f "$link" ]
then
if $SHOWME
then
- echo "+ ln $PROGLOG $link"
+ echo "+ ln $MYPROGLOG $link"
else
- ln $PROGLOG $link
+ ln $MYPROGLOG $link
fi
fi
fi
@@ -273,7 +307,7 @@
_unlock()
{
- rm -f lock
+ rm -f "$1/lock"
echo >$tmp/lock
}
@@ -395,6 +429,41 @@
echo "$pid"
}
+# wait for the local pmcd to get going for a primary pmlogger
+# (borrowed from qa/common.check)
+#
+# wait_for_pmcd [maxdelay]
+#
+_wait_for_pmcd()
+{
+ # 5 seconds default seems like a reasonable max time to get going
+ _can_wait=${1-5}
+ _limit=`expr $_can_wait \* 10`
+ _i=0
+ _dead=true
+ while [ $_i -lt $_limit ]
+ do
+ _sts=`pmprobe pmcd.numclients 2>/dev/null | $PCP_AWK_PROG '{print $2}'`
+ if [ "${_sts:-0}" -gt 0 ]
+ then
+ # numval really > 0, we're done
+ #
+ _dead=false
+ break
+ fi
+ pmsleep 0.1
+ _i=`expr $_i + 1`
+ done
+ if $_dead
+ then
+ date
+ echo "Arrgghhh ... pmcd at localhost failed to start after $_can_wait seconds"
+ echo "=== failing pmprobes ==="
+ pmprobe pmcd.numclients
+ status=1
+ fi
+}
+
_check_archive()
{
if [ ! -e "$logfile" ]
@@ -531,7 +600,17 @@
cd "$here"
line=`expr $line + 1`
- $VERY_VERBOSE && echo "[$controlfile:$line] host=\"$host\" primary=\"$primary\" socks=\"$socks\" dir=\"$dir\" args=\"$args\""
+
+ if $VERY_VERBOSE
+ then
+ case "$host"
+ in
+ \#*|'') # comment or empty
+ ;;
+ *) echo "[$controlfile:$line] host=\"$host\" primary=\"$primary\" socks=\"$socks\" dir=\"$dir\" args=\"$args\""
+ ;;
+ esac
+ fi
case "$host"
in
@@ -599,6 +678,15 @@
continue
fi
+ # if -s/--skip-primary on the command line, do not process
+ # a control file line for the primary pmlogger
+ #
+ if $SKIP_PRIMARY && [ $primary = y ]
+ then
+ $VERY_VERBOSE && echo "Skip, -s/--skip-primary on command line"
+ continue
+ fi
+
# substitute LOCALHOSTNAME marker in this config line
# (differently for directory and pcp -h HOST arguments)
#
@@ -610,7 +698,7 @@
then
pflag=''
[ $primary = y ] && pflag=' -P'
- echo "Check pmlogger$pflag -h $host ... in $dir ..."
+ echo "Checking for: pmlogger$pflag -h $host ... in $dir ..."
fi
# check for directory duplicate entries
@@ -664,19 +752,25 @@
delay=200 # tenths of a second
while [ $delay -gt 0 ]
do
- if pmlock -v lock >$tmp/out 2>&1
+ if pmlock -v "$dir/lock" >$tmp/out 2>&1
then
- echo $dir/lock >$tmp/lock
+ echo "$dir/lock" >$tmp/lock
+ if $VERY_VERBOSE
+ then
+ echo "Acquired lock:"
+ ls -l $dir/lock
+ fi
break
else
[ -f $tmp/stamp ] || touch -t `pmdate -30M %Y%m%d%H%M` $tmp/stamp
- if [ -z "`find lock -newer $tmp/stamp -print 2>/dev/null`" ]
+ find $tmp/stamp -newer "$dir/lock" -print 2>/dev/null >$tmp/tmp
+ if [ -s $tmp/tmp ]
then
- if [ -f lock ]
+ if [ -f "$dir/lock" ]
then
echo "$prog: Warning: removing lock file older than 30 minutes"
LC_TIME=POSIX ls -l $dir/lock
- rm -f lock
+ rm -f "$dir/lock"
else
# there is a small timing window here where pmlock
# might fail, but the lock file has been removed by
@@ -714,7 +808,7 @@
continue
fi
fi
- if [ -f lock ]
+ if [ -f "$dir/lock" ]
then
echo "$prog: Warning: is another PCP cron job running concurrently?"
LC_TIME=POSIX ls -l $dir/lock
@@ -753,6 +847,14 @@
$VERY_VERBOSE && echo "primary pmlogger process $pid not running"
pid=''
fi
+ else
+ if $VERY_VERBOSE
+ then
+ echo "$PCP_TMP_DIR/pmlogger/primary: missing?"
+ echo "Contents of $PCP_TMP_DIR/pmlogger"
+ ls -l $PCP_TMP_DIR/pmlogger
+ echo "--- end of ls output ---"
+ fi
fi
else
for log in $PCP_TMP_DIR/pmlogger/[0-9]*
@@ -798,6 +900,17 @@
#
PM_LOG_PORT_DIR="$PCP_TMP_DIR/pmlogger"
rm -f "$PM_LOG_PORT_DIR/primary"
+ # We really starting the primary pmlogger to work, especially
+ # in the systemd world, so make sure pmcd is ready to accept
+ # connections.
+ #
+ _wait_for_pmcd
+ if [ "$status" = 1 ]
+ then
+ $VERY_VERBOSE && echo "pmcd not running, skip primary pmlogger"
+ _unlock "$dir"
+ continue
+ fi
else
args="-h $host $args"
envs=""
@@ -870,7 +983,7 @@
then
echo
echo "+ ${sock_me}$PMLOGGER $args $LOGNAME"
- _unlock
+ _unlock "$dir"
continue
else
$PCP_BINADM_DIR/pmpost "start pmlogger from $prog for host $host"
@@ -903,7 +1016,7 @@
$PCP_ECHO_PROG $PCP_ECHO_N "$pid ""$PCP_ECHO_C" >> $tmp/pmloggers
fi
- _unlock
+ _unlock "$dir"
done
}
diff -auNr pcp-5.1.1-004/src/pmlogger/pmlogger_daily.sh pcp-5.1.1-005/src/pmlogger/pmlogger_daily.sh
--- pcp-5.1.1-004/src/pmlogger/pmlogger_daily.sh 2020-04-07 13:31:03.000000000 +1000
+++ pcp-5.1.1-005/src/pmlogger/pmlogger_daily.sh 2020-06-22 20:08:18.451403756 +1000
@@ -31,16 +31,24 @@
echo >$tmp/lock
prog=`basename $0`
PROGLOG=$PCP_LOG_DIR/pmlogger/$prog.log
+MYPROGLOG=$PROGLOG.$$
USE_SYSLOG=true
_cleanup()
{
+ if [ -s "$MYPROGLOG" ]
+ then
+ rm -f "$PROGLOG"
+ mv "$MYPROGLOG" "$PROGLOG"
+ else
+ rm -f "$MYPROGLOG"
+ fi
$USE_SYSLOG && [ $status -ne 0 ] && \
$PCP_SYSLOG_PROG -p daemon.error "$prog failed - see $PROGLOG"
- [ -s "$PROGLOG" ] || rm -f "$PROGLOG"
lockfile=`cat $tmp/lock 2>/dev/null`
rm -f "$lockfile" "$PCP_RUN_DIR/pmlogger_daily.pid"
rm -rf $tmp
+ $VERY_VERBOSE && echo "End: `date '+%F %T.%N'`"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -215,8 +223,10 @@
fi
COMPRESSONLY=true
PROGLOG=$PCP_LOG_DIR/pmlogger/$prog-K.log
+ MYPROGLOG=$PROGLOG.$$
;;
-l) PROGLOG="$2"
+ MYPROGLOG=$PROGLOG.$$
USE_SYSLOG=false
shift
;;
@@ -278,6 +288,7 @@
# $PCP_LOG_DIR/pmlogger/daily.<date>.trace
#
PROGLOG=$PCP_LOG_DIR/pmlogger/daily.`date "+%Y%m%d.%H.%M"`.trace
+ MYPROGLOG=$PROGLOG.$$
VERBOSE=true
VERY_VERBOSE=true
MYARGS="$MYARGS -V -V"
@@ -418,13 +429,23 @@
#
# Exception ($SHOWME, above) is for -N where we want to see the output.
#
- touch "$PROGLOG"
- chown $PCP_USER:$PCP_GROUP "$PROGLOG" >/dev/null 2>&1
- exec 1>"$PROGLOG" 2>&1
+ touch "$MYPROGLOG"
+ chown $PCP_USER:$PCP_GROUP "$MYPROGLOG" >/dev/null 2>&1
+ exec 1>"$MYPROGLOG" 2>&1
+fi
+
+if $VERY_VERBOSE
+then
+ echo "Start: `date '+%F %T.%N'`"
+ if `which pstree >/dev/null 2>&1`
+ then
+ echo "Called from:"
+ pstree -spa $$
+ fi
fi
# if SaveLogs exists in the $PCP_LOG_DIR/pmlogger directory then save
-# $PROGLOG there as well with a unique name that contains the date and time
+# $MYPROGLOG there as well with a unique name that contains the date and time
# when we're run ... skip if -N (showme)
#
if $SHOWME
@@ -433,15 +454,15 @@
else
if [ -d $PCP_LOG_DIR/pmlogger/SaveLogs ]
then
- now="`date '+%Y%m%d.%H.%M'`"
- link=`echo $PROGLOG | sed -e "s/$prog/SaveLogs\/$prog.$now/"`
+ now="`date '+%Y%m%d.%H.%M.%S'`"
+ link=`echo $MYPROGLOG | sed -e "s/$prog/SaveLogs\/$prog.$now/"`
if [ ! -f "$link" ]
then
if $SHOWME
then
- echo "+ ln $PROGLOG $link"
+ echo "+ ln $MYPROGLOG $link"
else
- ln $PROGLOG $link
+ ln $MYPROGLOG $link
fi
fi
fi
@@ -487,19 +508,20 @@
delay=200 # tenths of a second
while [ $delay -gt 0 ]
do
- if pmlock -v lock >>$tmp/out 2>&1
+ if pmlock -v "$1/lock" >>$tmp/out 2>&1
then
- echo $1/lock >$tmp/lock
+ echo "$1/lock" >$tmp/lock
break
else
[ -f $tmp/stamp ] || touch -t `pmdate -30M %Y%m%d%H%M` $tmp/stamp
- if [ ! -z "`find lock -newer $tmp/stamp -print 2>/dev/null`" ]
+ find $tmp/stamp -newer "$1/lock" -print 2>/dev/null >$tmp/tmp
+ if [ -s $tmp/tmp ]
then
- if [ -f lock ]
+ if [ -f "$1/lock" ]
then
_warning "removing lock file older than 30 minutes"
- LC_TIME=POSIX ls -l $1/lock
- rm -f lock
+ LC_TIME=POSIX ls -l "$1/lock"
+ rm -f "$1/lock"
else
# there is a small timing window here where pmlock
# might fail, but the lock file has been removed by
@@ -517,10 +539,10 @@
then
# failed to gain mutex lock
#
- if [ -f lock ]
+ if [ -f "$1/lock" ]
then
_warning "is another PCP cron job running concurrently?"
- LC_TIME=POSIX ls -l $1/lock
+ LC_TIME=POSIX ls -l "$1/lock"
else
echo "$prog: `cat $tmp/out`"
fi
@@ -534,7 +556,7 @@
_unlock()
{
- rm -f lock
+ rm -f "$1/lock"
echo >$tmp/lock
}
@@ -703,6 +725,9 @@
# if the directory containing the archive matches, then the name
# of the file is the pid.
#
+# The pid(s) (if any) appear on stdout, so be careful to send any
+# diagnostics to stderr.
+#
_get_non_primary_logger_pid()
{
pid=''
@@ -713,7 +738,7 @@
then
_host=`sed -n 2p <$log`
_arch=`sed -n 3p <$log`
- $PCP_ECHO_PROG $PCP_ECHO_N "... try $log host=$_host arch=$_arch: ""$PCP_ECHO_C"
+ $PCP_ECHO_PROG >&2 $PCP_ECHO_N "... try $log host=$_host arch=$_arch: ""$PCP_ECHO_C"
fi
# throw away stderr in case $log has been removed by now
match=`sed -e '3s@/[^/]*$@@' $log 2>/dev/null | \
@@ -721,19 +746,19 @@
BEGIN { m = 0 }
NR == 3 && $0 == "'$dir'" { m = 2; next }
END { print m }'`
- $VERY_VERBOSE && $PCP_ECHO_PROG $PCP_ECHO_N "match=$match ""$PCP_ECHO_C"
+ $VERY_VERBOSE && $PCP_ECHO_PROG >&2 $PCP_ECHO_N "match=$match ""$PCP_ECHO_C"
if [ "$match" = 2 ]
then
pid=`echo $log | sed -e 's,.*/,,'`
if _get_pids_by_name pmlogger | grep "^$pid\$" >/dev/null
then
- $VERY_VERBOSE && echo "pmlogger process $pid identified, OK"
+ $VERY_VERBOSE && echo >&2 "pmlogger process $pid identified, OK"
break
fi
- $VERY_VERBOSE && echo "pmlogger process $pid not running, skip"
+ $VERY_VERBOSE && echo >&2 "pmlogger process $pid not running, skip"
pid=''
else
- $VERY_VERBOSE && echo "different directory, skip"
+ $VERY_VERBOSE && echo >&2 "different directory, skip"
fi
done
echo "$pid"
@@ -1028,6 +1053,8 @@
pid=''
fi
else
+ # pid(s) on stdout, diagnostics on stderr
+ #
pid=`_get_non_primary_logger_pid`
if $VERY_VERBOSE
then
@@ -1458,7 +1485,7 @@
fi
fi
- _unlock
+ _unlock "$dir"
done
}
diff -auNr pcp-5.1.1-004/src/pmlogger/pmlogger.service.in pcp-5.1.1-005/src/pmlogger/pmlogger.service.in
--- pcp-5.1.1-004/src/pmlogger/pmlogger.service.in 2020-06-22 20:00:17.634331148 +1000
+++ pcp-5.1.1-005/src/pmlogger/pmlogger.service.in 2020-06-22 20:08:18.452403767 +1000
@@ -2,7 +2,7 @@
Description=Performance Metrics Archive Logger
Documentation=man:pmlogger(1)
After=network-online.target pmcd.service
-After=pmlogger_check.timer pmlogger_check.path pmlogger_daily.timer pmlogger_daily-poll.timer
+Before=pmlogger_check.timer pmlogger_check.path pmlogger_daily.timer pmlogger_daily-poll.timer
BindsTo=pmlogger_check.timer pmlogger_check.path pmlogger_daily.timer pmlogger_daily-poll.timer
Wants=pmcd.service
diff -auNr pcp-5.1.1-004/src/pmlogger/rc_pmlogger pcp-5.1.1-005/src/pmlogger/rc_pmlogger
--- pcp-5.1.1-004/src/pmlogger/rc_pmlogger 2020-04-21 10:42:02.000000000 +1000
+++ pcp-5.1.1-005/src/pmlogger/rc_pmlogger 2020-06-22 20:08:18.453403777 +1000
@@ -96,7 +96,7 @@
bgtmp=`mktemp -d $PCP_DIR/var/tmp/pcp.XXXXXXXXX` || exit 1
trap "rm -rf $bgtmp; exit \$bgstatus" 0 1 2 3 15
- pmlogger_check $VFLAG >$bgtmp/pmcheck.out 2>$bgtmp/pmcheck
+ pmlogger_check --quick $VFLAG >$bgtmp/pmcheck.out 2>$bgtmp/pmcheck
bgstatus=$?
if [ -s $bgtmp/pmcheck ]
then
@@ -125,8 +125,6 @@
false
else
# Really start the pmlogger instances based on the control file.
- # Done in the background to avoid delaying the init script,
- # failure notification is external (syslog, log files).
#
$ECHO $PCP_ECHO_N "Starting pmlogger ..." "$PCP_ECHO_C"
@@ -234,11 +232,9 @@
if [ $VERBOSE_CTL = on ]
then # For a verbose startup and shutdown
ECHO=$PCP_ECHO_PROG
- REBUILDOPT=''
VFLAG='-V'
else # For a quiet startup and shutdown
ECHO=:
- REBUILDOPT=-s
VFLAG=
fi
diff -auNr pcp-5.1.1-004/src/pmproxy/src/http.c pcp-5.1.1-005/src/pmproxy/src/http.c
--- pcp-5.1.1-004/src/pmproxy/src/http.c 2020-06-22 20:00:17.635331158 +1000
+++ pcp-5.1.1-005/src/pmproxy/src/http.c 2020-06-22 20:08:18.460403851 +1000
@@ -324,17 +324,36 @@
}
static sds
-http_response_trace(struct client *client)
+http_response_trace(struct client *client, int sts)
{
+ struct http_parser *parser = &client->u.http.parser;
dictIterator *iterator;
dictEntry *entry;
- sds result = sdsempty();
+ char buffer[64];
+ sds header;
+
+ parser->http_major = parser->http_minor = 1;
+
+ header = sdscatfmt(sdsempty(),
+ "HTTP/%u.%u %u %s\r\n"
+ "%S: Keep-Alive\r\n",
+ parser->http_major, parser->http_minor,
+ sts, http_status_mapping(sts), HEADER_CONNECTION);
+ header = sdscatfmt(header, "%S: %u\r\n", HEADER_CONTENT_LENGTH, 0);
iterator = dictGetSafeIterator(client->u.http.headers);
while ((entry = dictNext(iterator)) != NULL)
- result = sdscatfmt("%S: %S\r\n", dictGetKey(entry), dictGetVal(entry));
+ header = sdscatfmt(header, "%S: %S\r\n", dictGetKey(entry), dictGetVal(entry));
dictReleaseIterator(iterator);
- return result;
+
+ header = sdscatfmt(header, "Date: %s\r\n\r\n",
+ http_date_string(time(NULL), buffer, sizeof(buffer)));
+
+ if (pmDebugOptions.http && pmDebugOptions.desperate) {
+ fprintf(stderr, "trace response to client %p\n", client);
+ fputs(header, stderr);
+ }
+ return header;
}
static sds
@@ -418,7 +437,7 @@
if (client->u.http.parser.method == HTTP_OPTIONS)
buffer = http_response_access(client, sts, options);
else if (client->u.http.parser.method == HTTP_TRACE)
- buffer = http_response_trace(client);
+ buffer = http_response_trace(client, sts);
else /* HTTP_HEAD */
buffer = http_response_header(client, 0, sts, type);
suffix = NULL;
@@ -533,6 +552,8 @@
if (servlet && servlet->on_release)
servlet->on_release(client);
client->u.http.privdata = NULL;
+ client->u.http.servlet = NULL;
+ client->u.http.flags = 0;
if (client->u.http.headers) {
dictRelease(client->u.http.headers);
@@ -696,29 +717,39 @@
{
struct client *client = (struct client *)request->data;
struct servlet *servlet;
- sds buffer;
int sts;
http_client_release(client); /* new URL, clean slate */
- /* server options - https://tools.ietf.org/html/rfc7231#section-4.3.7 */
- if (length == 1 && *offset == '*' &&
- client->u.http.parser.method == HTTP_OPTIONS) {
- buffer = http_response_access(client, HTTP_STATUS_OK, HTTP_SERVER_OPTIONS);
- client_write(client, buffer, NULL);
- } else if ((servlet = servlet_lookup(client, offset, length)) != NULL) {
+ /* pass to servlets handling each of our internal request endpoints */
+ if ((servlet = servlet_lookup(client, offset, length)) != NULL) {
client->u.http.servlet = servlet;
- if ((sts = client->u.http.parser.status_code) == 0) {
+ if ((sts = client->u.http.parser.status_code) != 0)
+ http_error(client, sts, "failed to process URL");
+ else {
if (client->u.http.parser.method == HTTP_OPTIONS ||
client->u.http.parser.method == HTTP_TRACE ||
client->u.http.parser.method == HTTP_HEAD)
client->u.http.flags |= HTTP_FLAG_NO_BODY;
- else
- client->u.http.flags &= ~HTTP_FLAG_NO_BODY;
client->u.http.headers = dictCreate(&sdsOwnDictCallBacks, NULL);
- return 0;
}
- http_error(client, sts, "failed to process URL");
- } else {
+ }
+ /* server options - https://tools.ietf.org/html/rfc7231#section-4.3.7 */
+ else if (client->u.http.parser.method == HTTP_OPTIONS) {
+ if (length == 1 && *offset == '*') {
+ client->u.http.flags |= HTTP_FLAG_NO_BODY;
+ client->u.http.headers = dictCreate(&sdsOwnDictCallBacks, NULL);
+ } else {
+ sts = client->u.http.parser.status_code = HTTP_STATUS_BAD_REQUEST;
+ http_error(client, sts, "no handler for OPTIONS");
+ }
+ }
+ /* server trace - https://tools.ietf.org/html/rfc7231#section-4.3.8 */
+ else if (client->u.http.parser.method == HTTP_TRACE) {
+ client->u.http.flags |= HTTP_FLAG_NO_BODY;
+ client->u.http.headers = dictCreate(&sdsOwnDictCallBacks, NULL);
+ }
+ /* nothing available to respond to this request - inform the client */
+ else {
sts = client->u.http.parser.status_code = HTTP_STATUS_BAD_REQUEST;
http_error(client, sts, "no handler for URL");
}
@@ -734,7 +765,7 @@
if (pmDebugOptions.http && pmDebugOptions.desperate)
printf("Body: %.*s\n(client=%p)\n", (int)length, offset, client);
- if (servlet->on_body)
+ if (servlet && servlet->on_body)
return servlet->on_body(client, offset, length);
return 0;
}
@@ -828,7 +859,7 @@
}
client->u.http.privdata = NULL;
- if (servlet->on_headers)
+ if (servlet && servlet->on_headers)
sts = servlet->on_headers(client, client->u.http.headers);
/* HTTP Basic Auth for all servlets */
@@ -857,13 +888,31 @@
{
struct client *client = (struct client *)request->data;
struct servlet *servlet = client->u.http.servlet;
+ sds buffer;
+ int sts;
if (pmDebugOptions.http)
fprintf(stderr, "HTTP message complete (client=%p)\n", client);
- if (servlet && servlet->on_done)
- return servlet->on_done(client);
- return 0;
+ if (servlet) {
+ if (servlet->on_done)
+ return servlet->on_done(client);
+ return 0;
+ }
+
+ sts = HTTP_STATUS_OK;
+ if (client->u.http.parser.method == HTTP_OPTIONS) {
+ buffer = http_response_access(client, sts, HTTP_SERVER_OPTIONS);
+ client_write(client, buffer, NULL);
+ return 0;
+ }
+ if (client->u.http.parser.method == HTTP_TRACE) {
+ buffer = http_response_trace(client, sts);
+ client_write(client, buffer, NULL);
+ return 0;
+ }
+
+ return 1;
}
void
diff -auNr pcp-5.1.1.orig/qa/1608 pcp-5.1.1/qa/1608
--- pcp-5.1.1.orig/qa/1608 1970-01-01 10:00:00.000000000 +1000
+++ pcp-5.1.1/qa/1608 2020-06-23 12:16:04.005557293 +1000
@@ -0,0 +1,58 @@
+#!/bin/sh
+# PCP QA Test No. 1608
+# Exercise a long URL handling in pmproxy.
+#
+# Copyright (c) 2020 Red Hat. All Rights Reserved.
+#
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+# get standard environment, filters and checks
+. ./common.product
+. ./common.filter
+. ./common.check
+
+_check_series
+which curl >/dev/null 2>&1 || _notrun "No curl binary installed"
+
+status=1 # failure is the default!
+$sudo rm -rf $tmp $tmp.* $seq.full
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+pmproxy_was_running=false
+[ -f $PCP_RUN_DIR/pmproxy.pid ] && pmproxy_was_running=true
+echo "pmproxy_was_running=$pmproxy_was_running" >>$here/$seq.full
+
+_cleanup()
+{
+ if $pmproxy_was_running
+ then
+ echo "Restart pmproxy ..." >>$here/$seq.full
+ _service pmproxy restart >>$here/$seq.full 2>&1
+ _wait_for_pmproxy
+ else
+ echo "Stopping pmproxy ..." >>$here/$seq.full
+ _service pmproxy stop >>$here/$seq.full 2>&1
+ fi
+ $sudo rm -f $tmp.*
+}
+
+_webapi_failure_filter()
+{
+ _webapi_header_filter | \
+ sed \
+ -e 's/pmproxy.[0-9][0-9]*.[0-9][0-9]*.[0-9][0-9]*/PMPROXY\/VERSION/g' \
+ #end
+}
+
+# real QA test starts here
+_service pmproxy restart >/dev/null 2>&1
+
+url="http://localhost:44322/pmapi/context"
+aaa=`head -c 10000 < /dev/zero | tr '\0' '\141'`
+curl -isS -X OPTIONS "${url}?${aaa}" | _webapi_failure_filter
+
+# success, all done
+status=0
+exit
diff -auNr pcp-5.1.1.orig/qa/1608.out pcp-5.1.1/qa/1608.out
--- pcp-5.1.1.orig/qa/1608.out 1970-01-01 10:00:00.000000000 +1000
+++ pcp-5.1.1/qa/1608.out 2020-06-23 12:16:04.005557293 +1000
@@ -0,0 +1,16 @@
+QA output created by 1608
+
+</body>
+</html>
+<body>
+<h1>414 URI Too Long</h1>
+<head><title>414 URI Too Long</title></head>
+<html>
+<p><b>unknown servlet</b>: request URL too long</p><hr>
+<p><small><i>PMPROXY/VERSION</i></small></p>
+Access-Control-Allow-Headers: Accept, Accept-Language, Content-Language, Content-Type
+Access-Control-Allow-Origin: *
+Content-Length: SIZE
+Content-Type: text/html
+Date: DATE
+HTTP/1.1 414 URI Too Long
diff -auNr pcp-5.1.1.orig/qa/group pcp-5.1.1/qa/group
--- pcp-5.1.1.orig/qa/group 2020-06-23 12:15:21.335094106 +1000
+++ pcp-5.1.1/qa/group 2020-06-23 12:16:54.256102754 +1000
@@ -1717,6 +1717,7 @@
1600 pmseries pmcd pmproxy pmlogger local
1601 pmseries pmproxy local
1602 pmproxy local
+1608 pmproxy local
1622 selinux local
1623 libpcp_import collectl local
1644 pmda.perfevent local
diff -auNr pcp-5.1.1.orig/src/pmproxy/src/http.c pcp-5.1.1/src/pmproxy/src/http.c
--- pcp-5.1.1.orig/src/pmproxy/src/http.c 2020-06-23 12:15:21.364094421 +1000
+++ pcp-5.1.1/src/pmproxy/src/http.c 2020-06-23 12:16:04.008557325 +1000
@@ -21,7 +21,9 @@
static int chunked_transfer_size; /* pmproxy.chunksize, pagesize by default */
static int smallest_buffer_size = 128;
-#define MAX_PARAMS_SIZE 4096
+/* https://tools.ietf.org/html/rfc7230#section-3.1.1 */
+#define MAX_URL_SIZE 8192
+#define MAX_PARAMS_SIZE 8000
#define MAX_HEADERS_SIZE 128
static sds HEADER_ACCESS_CONTROL_REQUEST_HEADERS,
@@ -720,8 +722,13 @@
int sts;
http_client_release(client); /* new URL, clean slate */
+
+ if (length >= MAX_URL_SIZE) {
+ sts = client->u.http.parser.status_code = HTTP_STATUS_URI_TOO_LONG;
+ http_error(client, sts, "request URL too long");
+ }
/* pass to servlets handling each of our internal request endpoints */
- if ((servlet = servlet_lookup(client, offset, length)) != NULL) {
+ else if ((servlet = servlet_lookup(client, offset, length)) != NULL) {
client->u.http.servlet = servlet;
if ((sts = client->u.http.parser.status_code) != 0)
http_error(client, sts, "failed to process URL");