Blame SOURCES/redhat-bugzilla-2030140.patch

f76dca
diff -Naurp pcp-5.3.5.orig/qa/1458 pcp-5.3.5/qa/1458
f76dca
--- pcp-5.3.5.orig/qa/1458	1970-01-01 10:00:00.000000000 +1000
f76dca
+++ pcp-5.3.5/qa/1458	2021-12-09 11:25:01.973327231 +1100
f76dca
@@ -0,0 +1,219 @@
f76dca
+#!/bin/sh
f76dca
+# PCP QA Test No. 1458
f76dca
+# Exercise access pmproxy with secure.enabled = false
f76dca
+#
f76dca
+# The main purpose of this is to test that the component works correctly
f76dca
+# when secure.enabled = false; we can expect the https URLs to fail.
f76dca
+#
f76dca
+# See https://github.com/performancecopilot/pcp/issues/1490
f76dca
+
f76dca
+# Copyright (c) 2019,2021 Red Hat
f76dca
+# Modified by Netflix, Inc.
f76dca
+#
f76dca
+
f76dca
+seq=`basename $0`
f76dca
+echo "QA output created by $seq"
f76dca
+
f76dca
+# get standard environment, filters and checks
f76dca
+. ./common.product
f76dca
+. ./common.filter
f76dca
+. ./common.check
f76dca
+
f76dca
+_check_series	# pmseries availability means libuv is in use
f76dca
+_check_valgrind
f76dca
+openssl help 2>/dev/null || _notrun "No openssl binary found"
f76dca
+
f76dca
+if [ -f /etc/lsb-release ]
f76dca
+then
f76dca
+    . /etc/lsb-release
f76dca
+    if [ "$DISTRIB_ID" = Ubuntu ]
f76dca
+    then
f76dca
+	# This test fails for Ubuntu 19.10 with a myriad of errors involving
f76dca
+	# the use of uninitialized values.  The code paths very but typically
f76dca
+	# involve libuv -> libssl ->  libcrypto
f76dca
+	#
f76dca
+	case "$DISTRIB_RELEASE"
f76dca
+	in
f76dca
+	    19.10)
f76dca
+		_notrun "problems with libuv, libssl, libcrypto and valgrind on Ubuntu $DISTRIB_RELEASE"
f76dca
+		;;
f76dca
+	esac
f76dca
+    fi
f76dca
+fi
f76dca
+
f76dca
+_cleanup()
f76dca
+{
f76dca
+    cd $here
f76dca
+    if $need_restore
f76dca
+    then
f76dca
+	need_restore=false
f76dca
+	_restore_config $PCP_SYSCONF_DIR/labels
f76dca
+	_sighup_pmcd
f76dca
+    fi
f76dca
+    $sudo rm -rf $tmp $tmp.*
f76dca
+}
f76dca
+
f76dca
+status=1	# failure is the default!
f76dca
+need_restore=false
f76dca
+username=`id -u -n`
f76dca
+$sudo rm -rf $tmp $tmp.* $seq.full
f76dca
+trap "_cleanup; exit \$status" 0 1 2 3 15
f76dca
+
f76dca
+_check_empty()
f76dca
+{
f76dca
+    tee -a $seq.full > $tmp.unfiltered
f76dca
+    if [ -s $tmp.unfiltered ]
f76dca
+    then
f76dca
+	echo "Botch: got output from curl"
f76dca
+    else
f76dca
+	echo "Good!, empty output from curl"
f76dca
+    fi
f76dca
+}
f76dca
+
f76dca
+_filter_json()
f76dca
+{
f76dca
+    tee -a $seq.full > $tmp.unfiltered
f76dca
+    if [ -s $tmp.unfiltered ]
f76dca
+    then
f76dca
+	pmjson < $tmp.unfiltered > $tmp.filtered
f76dca
+	status=$?
f76dca
+	    if [ $status -eq 0 ]; then
f76dca
+	    cat $tmp.filtered | \
f76dca
+	    sed \
f76dca
+		-e '/"machineid": .*/d' \
f76dca
+		-e 's,"series": .*,"series": "SERIES",g' \
f76dca
+		-e 's,"context": .*,"context": "CONTEXT",g' \
f76dca
+		-e 's,"hostname": .*,"hostname": "HOSTNAME",g' \
f76dca
+		-e 's,"domainname": .*,"domainname": "DOMAINNAME",g' \
f76dca
+	    #end
f76dca
+	else
f76dca
+	    echo "Invalid JSON: $status"
f76dca
+	    cat $tmp.unfiltered
f76dca
+	    rm -f $tmp.context
f76dca
+	fi
f76dca
+    else
f76dca
+	echo "Botch: no output from curl"
f76dca
+    fi
f76dca
+}
f76dca
+
f76dca
+_filter_port()
f76dca
+{
f76dca
+    sed \
f76dca
+        -e '/ ipv6 /d' \
f76dca
+	-e "s/ $port / PORT /g" \
f76dca
+    #end
f76dca
+}
f76dca
+
f76dca
+# real QA test starts here
f76dca
+_save_config $PCP_SYSCONF_DIR/labels
f76dca
+need_restore=true
f76dca
+
f76dca
+$sudo rm -rf $PCP_SYSCONF_DIR/labels/*
f76dca
+_sighup_pmcd
f76dca
+
f76dca
+openssl req \
f76dca
+	-new -newkey rsa:4096 -days 365 -nodes -x509 \
f76dca
+	-subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.pcpqa.com" \
f76dca
+	-keyout $tmp.key -out $tmp.cert >$seq.full 2>&1
f76dca
+# creates a self-signed (insecure) certificate, so for testing only
f76dca
+
f76dca
+echo "[pmproxy]" >> $tmp.conf
f76dca
+echo "pcp.enabled = true" >> $tmp.conf
f76dca
+echo "http.enabled = true" >> $tmp.conf
f76dca
+echo "redis.enabled = false" >> $tmp.conf
f76dca
+echo "secure.enabled = false" >> $tmp.conf
f76dca
+
f76dca
+port=`_find_free_port`
f76dca
+mkdir -p $tmp.pmproxy/pmproxy
f76dca
+export PCP_RUN_DIR=$tmp.pmproxy
f76dca
+export PCP_TMP_DIR=$tmp.pmproxy
f76dca
+
f76dca
+$_valgrind_clean_assert pmproxy -f -l- --timeseries \
f76dca
+	-c $tmp.conf -p $port -U $username \
f76dca
+	>$tmp.valout 2>$tmp.valerr &
f76dca
+pid=$!
f76dca
+
f76dca
+echo "valgrind pid: $pid" >>$seq.full
f76dca
+echo "pmproxy port: $port" >>$seq.full
f76dca
+
f76dca
+# valgrind takes awhile to fire up
f76dca
+i=0
f76dca
+while [ $i -lt 40 ]
f76dca
+do
f76dca
+    $PCP_BINADM_DIR/telnet-probe -c localhost $port && break
f76dca
+    sleep 1
f76dca
+    i=`expr $i + 1`
f76dca
+done
f76dca
+if $PCP_BINADM_DIR/telnet-probe -c localhost $port
f76dca
+then
f76dca
+    echo "Startup took $i secs" >>$seq.full
f76dca
+else
f76dca
+    echo "Arrgh: valgrind failed start pmproxy and get port $port ready after 30 secs"
f76dca
+    exit
f76dca
+fi
f76dca
+
f76dca
+date >>$seq.full
f76dca
+echo "=== checking serial http operation ===" | tee -a $seq.full
f76dca
+for i in 1 2 3 4; do
f76dca
+    curl -Gs "http://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i
f76dca
+done
f76dca
+for i in 1 2 3 4; do
f76dca
+echo === out$i === | tee -a $seq.full
f76dca
+_filter_json < $tmp.out$i
f76dca
+done
f76dca
+
f76dca
+date >>$seq.full
f76dca
+echo "=== checking parallel http operation ===" | tee -a $seq.full
f76dca
+for i in 1 2 3 4; do
f76dca
+    curl -Gs "http://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i & 2>/dev/null eval pid$i=$!
f76dca
+done
f76dca
+wait $pid1 $pid2 $pid3 $pid4
f76dca
+for i in 1 2 3 4; do
f76dca
+echo === out$i === | tee -a $seq.full
f76dca
+_filter_json < $tmp.out$i
f76dca
+done
f76dca
+
f76dca
+date >>$seq.full
f76dca
+echo "=== checking serial https/TLS operation ===" | tee -a $seq.full
f76dca
+for i in 1 2 3 4; do
f76dca
+    curl -k -Gs "https://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i
f76dca
+done
f76dca
+for i in 1 2 3 4; do
f76dca
+echo === out$i === | tee -a $seq.full
f76dca
+_check_empty < $tmp.out$i
f76dca
+done
f76dca
+
f76dca
+date >>$seq.full
f76dca
+echo "=== checking parallel https/TLS operation ===" | tee -a $seq.full
f76dca
+for i in 1 2 3 4; do
f76dca
+    curl -k -Gs "https://localhost:$port/pmapi/metric?name=sample.long.ten" 2>$tmp.err$i >$tmp.out$i & 2>/dev/null eval pid$i=$!
f76dca
+done
f76dca
+wait $pid1 $pid2 $pid3 $pid4
f76dca
+for i in 1 2 3 4; do
f76dca
+echo === out$i === | tee -a $seq.full
f76dca
+_check_empty < $tmp.out$i
f76dca
+done
f76dca
+
f76dca
+echo "=== check pmproxy is running ==="
f76dca
+pminfo -v -h localhost@localhost:$port hinv.ncpu
f76dca
+if [ $? -eq 0 ]; then
f76dca
+    echo "pmproxy check passed"
f76dca
+else
f76dca
+    echo "pmproxy check failed"
f76dca
+fi
f76dca
+
f76dca
+# valgrind takes awhile to shutdown too
f76dca
+pmsignal $pid >/dev/null 2>&1
f76dca
+pmsleep 3.5
f76dca
+echo "=== valgrind stdout ===" | tee -a $seq.full
f76dca
+cat $tmp.valout | _filter_valgrind
f76dca
+
f76dca
+echo "=== valgrind stderr ===" | tee -a $seq.full
f76dca
+cat $tmp.valerr | _filter_pmproxy_log | _filter_port
f76dca
+
f76dca
+# final kill if it's spinning
f76dca
+$sudo kill -9 $pid >/dev/null 2>&1
f76dca
+
f76dca
+# success, all done
f76dca
+status=0
f76dca
+exit
f76dca
diff -Naurp pcp-5.3.5.orig/qa/1458.out pcp-5.3.5/qa/1458.out
f76dca
--- pcp-5.3.5.orig/qa/1458.out	1970-01-01 10:00:00.000000000 +1000
f76dca
+++ pcp-5.3.5/qa/1458.out	2021-12-09 11:25:01.973327231 +1100
f76dca
@@ -0,0 +1,221 @@
f76dca
+QA output created by 1458
f76dca
+=== checking serial http operation ===
f76dca
+=== out1 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== out2 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== out3 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== out4 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== checking parallel http operation ===
f76dca
+=== out1 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== out2 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== out3 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== out4 ===
f76dca
+{
f76dca
+    "context": "CONTEXT"
f76dca
+    "metrics": [
f76dca
+        {
f76dca
+            "name": "sample.long.ten",
f76dca
+            "series": "SERIES"
f76dca
+            "pmid": "29.0.11",
f76dca
+            "type": "32",
f76dca
+            "sem": "instant",
f76dca
+            "units": "none",
f76dca
+            "labels": {
f76dca
+                "agent": "sample",
f76dca
+                "cluster": "zero",
f76dca
+                "domainname": "DOMAINNAME"
f76dca
+                "hostname": "HOSTNAME"
f76dca
+                "role": "testing"
f76dca
+            },
f76dca
+            "text-oneline": "10 as a 32-bit integer",
f76dca
+            "text-help": "10 as a 32-bit integer"
f76dca
+        }
f76dca
+    ]
f76dca
+}
f76dca
+=== checking serial https/TLS operation ===
f76dca
+=== out1 ===
f76dca
+Good!, empty output from curl
f76dca
+=== out2 ===
f76dca
+Good!, empty output from curl
f76dca
+=== out3 ===
f76dca
+Good!, empty output from curl
f76dca
+=== out4 ===
f76dca
+Good!, empty output from curl
f76dca
+=== checking parallel https/TLS operation ===
f76dca
+=== out1 ===
f76dca
+Good!, empty output from curl
f76dca
+=== out2 ===
f76dca
+Good!, empty output from curl
f76dca
+=== out3 ===
f76dca
+Good!, empty output from curl
f76dca
+=== out4 ===
f76dca
+Good!, empty output from curl
f76dca
+=== check pmproxy is running ===
f76dca
+pmproxy check passed
f76dca
+=== valgrind stdout ===
f76dca
+=== valgrind stderr ===
f76dca
+Log for pmproxy on HOST started DATE
f76dca
+
f76dca
+pmproxy: PID = PID
f76dca
+pmproxy request port(s):
f76dca
+  sts fd   port  family address
f76dca
+  === ==== ===== ====== =======
f76dca
+ok FD unix UNIX_DOMAIN_SOCKET
f76dca
+ok FD PORT inet INADDR_ANY
f76dca
+[DATE] pmproxy(PID) Info: pmproxy caught SIGTERM
f76dca
+[DATE] pmproxy(PID) Info: pmproxy Shutdown
f76dca
+
f76dca
+Log finished DATE
f76dca
diff -Naurp pcp-5.3.5.orig/src/pmproxy/src/pcp.c pcp-5.3.5/src/pmproxy/src/pcp.c
f76dca
--- pcp-5.3.5.orig/src/pmproxy/src/pcp.c	2021-09-24 09:33:06.000000000 +1000
f76dca
+++ pcp-5.3.5/src/pmproxy/src/pcp.c	2021-12-09 11:22:09.829321418 +1100
f76dca
@@ -1,6 +1,6 @@
f76dca
 /*
f76dca
- * Copyright (c) 2018-2019 Red Hat.
f76dca
- * 
f76dca
+ * Copyright (c) 2018-2019,2021 Red Hat.
f76dca
+ *
f76dca
  * This program is free software; you can redistribute it and/or modify it
f76dca
  * under the terms of the GNU Lesser General Public License as published
f76dca
  * by the Free Software Foundation; either version 2.1 of the License, or
f76dca
@@ -19,22 +19,13 @@
f76dca
 #define PDU_MAXLENGTH	(MAXHOSTNAMELEN + HEADER_LENGTH + sizeof("65536")-1)
f76dca
 
f76dca
 static void
f76dca
-client_free(struct client *client)
f76dca
-{
f76dca
-    if (client->u.pcp.hostname)
f76dca
-	sdsfree(client->u.pcp.hostname);
f76dca
-    if (client->buffer)
f76dca
-	sdsfree(client->buffer);
f76dca
-}
f76dca
-
f76dca
-static void
f76dca
 on_server_close(uv_handle_t *handle)
f76dca
 {
f76dca
     struct client	*client = (struct client *)handle;
f76dca
 
f76dca
     if (pmDebugOptions.pdu)
f76dca
 	fprintf(stderr, "client %p pmcd connection closed\n", client);
f76dca
-    client_free(client);
f76dca
+    client_put(client);
f76dca
 }
f76dca
 
f76dca
 static void
f76dca
@@ -92,12 +83,11 @@ on_server_read(uv_stream_t *stream, ssiz
f76dca
 void
f76dca
 on_pcp_client_close(struct client *client)
f76dca
 {
f76dca
-    if (client->u.pcp.connected) {
f76dca
+    if (client->u.pcp.connected)
f76dca
 	uv_close((uv_handle_t *)&client->u.pcp.socket, on_server_close);
f76dca
-	memset(&client->u.pcp, 0, sizeof(client->u.pcp));
f76dca
-    } else {
f76dca
-	client_free(client);
f76dca
-    }
f76dca
+    if (client->u.pcp.hostname)
f76dca
+	sdsfree(client->u.pcp.hostname);
f76dca
+    memset(&client->u.pcp, 0, sizeof(client->u.pcp));
f76dca
 }
f76dca
 
f76dca
 static void
f76dca
@@ -118,6 +108,8 @@ on_pcp_client_connect(uv_connect_t *conn
f76dca
 
f76dca
     /* socket connection to pmcd successfully established */
f76dca
     client->u.pcp.state = PCP_PROXY_SETUP;
f76dca
+    client->u.pcp.connected = 1;
f76dca
+    client_get(client);
f76dca
 
f76dca
     /* if we have already received PDUs, send them on now */
f76dca
     if ((buffer = client->buffer) != NULL) {
f76dca
diff -Naurp pcp-5.3.5.orig/src/pmproxy/src/secure.c pcp-5.3.5/src/pmproxy/src/secure.c
f76dca
--- pcp-5.3.5.orig/src/pmproxy/src/secure.c	2021-11-01 13:02:26.000000000 +1100
f76dca
+++ pcp-5.3.5/src/pmproxy/src/secure.c	2021-12-09 11:22:09.831321384 +1100
f76dca
@@ -1,5 +1,5 @@
f76dca
 /*
f76dca
- * Copyright (c) 2019 Red Hat.
f76dca
+ * Copyright (c) 2019,2021 Red Hat.
f76dca
  *
f76dca
  * This program is free software; you can redistribute it and/or modify it
f76dca
  * under the terms of the GNU Lesser General Public License as published
f76dca
@@ -16,7 +16,7 @@
f76dca
 #include <openssl/opensslv.h>
f76dca
 #include <openssl/ssl.h>
f76dca
 
f76dca
-/* called with proxy->mutex locked */
f76dca
+/* called with proxy->write_mutex locked */
f76dca
 static void
f76dca
 remove_connection_from_queue(struct client *client)
f76dca
 {
f76dca
@@ -44,9 +44,9 @@ on_secure_client_close(struct client *cl
f76dca
     if (pmDebugOptions.auth || pmDebugOptions.http)
f76dca
 	fprintf(stderr, "%s: client %p\n", "on_secure_client_close", client);
f76dca
 
f76dca
-    uv_mutex_lock(&client->proxy->mutex);
f76dca
+    uv_mutex_lock(&client->proxy->write_mutex);
f76dca
     remove_connection_from_queue(client);
f76dca
-    uv_mutex_unlock(&client->proxy->mutex);
f76dca
+    uv_mutex_unlock(&client->proxy->write_mutex);
f76dca
     /* client->read and client->write freed by SSL_free */
f76dca
     SSL_free(client->secure.ssl);
f76dca
 }
f76dca
@@ -63,7 +63,7 @@ maybe_flush_ssl(struct proxy *proxy, str
f76dca
 	client->secure.pending.writes_count > 0)
f76dca
 	return;
f76dca
 
f76dca
-    uv_mutex_lock(&proxy->mutex);
f76dca
+    uv_mutex_lock(&proxy->write_mutex);
f76dca
     if (proxy->pending_writes == NULL) {
f76dca
     	proxy->pending_writes = client;
f76dca
 	client->secure.pending.prev = client->secure.pending.next = NULL;
f76dca
@@ -75,7 +75,7 @@ maybe_flush_ssl(struct proxy *proxy, str
f76dca
 	client->secure.pending.prev = c;
f76dca
     }
f76dca
     client->secure.pending.queued = 1;
f76dca
-    uv_mutex_unlock(&proxy->mutex);
f76dca
+    uv_mutex_unlock(&proxy->write_mutex);
f76dca
 }
f76dca
 
f76dca
 static void
f76dca
@@ -161,7 +161,7 @@ flush_secure_module(struct proxy *proxy)
f76dca
     size_t		i, used;
f76dca
     int			sts;
f76dca
 
f76dca
-    uv_mutex_lock(&proxy->mutex);
f76dca
+    uv_mutex_lock(&proxy->write_mutex);
f76dca
     head = &proxy->pending_writes;
f76dca
     while ((client = *head) != NULL) {
f76dca
 	flush_ssl_buffer(client);
f76dca
@@ -212,7 +212,7 @@ flush_secure_module(struct proxy *proxy)
f76dca
 		    sizeof(uv_buf_t) * client->secure.pending.writes_count);
f76dca
 	}
f76dca
     }
f76dca
-    uv_mutex_unlock(&proxy->mutex);
f76dca
+    uv_mutex_unlock(&proxy->write_mutex);
f76dca
 }
f76dca
 
f76dca
 void
f76dca
@@ -221,7 +221,8 @@ secure_client_write(struct client *clien
f76dca
     struct proxy	*proxy = client->proxy;
f76dca
     uv_buf_t		*dup;
f76dca
     size_t		count, bytes;
f76dca
-    int			i, sts, defer = 0, maybe = 0;
f76dca
+    unsigned int	i;
f76dca
+    int			sts, defer = 0, maybe = 0;
f76dca
 
f76dca
     for (i = 0; i < request->nbuffers; i++) {
f76dca
 	if (defer == 0) {
f76dca
diff -Naurp pcp-5.3.5.orig/src/pmproxy/src/server.c pcp-5.3.5/src/pmproxy/src/server.c
f76dca
--- pcp-5.3.5.orig/src/pmproxy/src/server.c	2021-11-01 13:02:26.000000000 +1100
f76dca
+++ pcp-5.3.5/src/pmproxy/src/server.c	2021-12-09 11:22:09.831321384 +1100
f76dca
@@ -1,5 +1,5 @@
f76dca
 /*
f76dca
- * Copyright (c) 2018-2019 Red Hat.
f76dca
+ * Copyright (c) 2018-2019,2021 Red Hat.
f76dca
  *
f76dca
  * This program is free software; you can redistribute it and/or modify it
f76dca
  * under the terms of the GNU Lesser General Public License as published
f76dca
@@ -125,7 +125,7 @@ server_init(int portcount, const char *l
f76dca
 			pmGetProgname());
f76dca
 	return NULL;
f76dca
     }
f76dca
-    uv_mutex_init(&proxy->mutex);
f76dca
+    uv_mutex_init(&proxy->write_mutex);
f76dca
 
f76dca
     count = portcount + (*localpath ? 1 : 0);
f76dca
     if (count) {
f76dca
@@ -229,7 +229,6 @@ void
f76dca
 client_put(struct client *client)
f76dca
 {
f76dca
     unsigned int	refcount;
f76dca
-    struct proxy	*proxy = client->proxy;
f76dca
 
f76dca
     uv_mutex_lock(&client->mutex);
f76dca
     assert(client->refcount);
f76dca
@@ -237,22 +236,16 @@ client_put(struct client *client)
f76dca
     uv_mutex_unlock(&client->mutex);
f76dca
 
f76dca
     if (refcount == 0) {
f76dca
-	/* remove client from the doubly-linked list */
f76dca
-	uv_mutex_lock(&proxy->mutex);
f76dca
-	if (client->next != NULL)
f76dca
-	    client->next->prev = client->prev;
f76dca
-	*client->prev = client->next;
f76dca
-	uv_mutex_unlock(&proxy->mutex);
f76dca
-
f76dca
 	if (client->protocol & STREAM_PCP)
f76dca
 	    on_pcp_client_close(client);
f76dca
 	if (client->protocol & STREAM_HTTP)
f76dca
 	    on_http_client_close(client);
f76dca
 	if (client->protocol & STREAM_REDIS)
f76dca
 	    on_redis_client_close(client);
f76dca
-	if (client->protocol & STREAM_SECURE)
f76dca
+	if ((client->protocol & STREAM_SECURE) && client->stream.secure)
f76dca
 	    on_secure_client_close(client);
f76dca
-
f76dca
+	if (client->buffer)
f76dca
+	    sdsfree(client->buffer);
f76dca
 	memset(client, 0, sizeof(*client));
f76dca
 	free(client);
f76dca
     }
f76dca
@@ -284,7 +277,7 @@ on_client_write(uv_write_t *writer, int
f76dca
 			"on_client_write", status, client);
f76dca
 
f76dca
     if (status == 0) {
f76dca
-	if (client->protocol & STREAM_SECURE)
f76dca
+	if ((client->protocol & STREAM_SECURE) && client->stream.secure)
f76dca
 	    on_secure_client_write(client);
f76dca
 	if (client->protocol & STREAM_PCP)
f76dca
 	    on_pcp_client_write(client);
f76dca
@@ -434,10 +427,16 @@ on_client_read(uv_stream_t *stream, ssiz
f76dca
     if (nread > 0) {
f76dca
 	if (client->protocol == STREAM_UNKNOWN)
f76dca
 	    client->protocol |= client_protocol(*buf->base);
f76dca
-	if (client->protocol & STREAM_SECURE)
f76dca
+
f76dca
+#ifdef HAVE_OPENSSL
f76dca
+	if ((client->protocol & STREAM_SECURE) && (proxy->ssl != NULL))
f76dca
 	    on_secure_client_read(proxy, client, nread, buf);
f76dca
 	else
f76dca
 	    on_protocol_read(stream, nread, buf);
f76dca
+#else
f76dca
+	on_protocol_read(stream, nread, buf);
f76dca
+#endif
f76dca
+
f76dca
     } else if (nread < 0) {
f76dca
 	if (pmDebugOptions.af)
f76dca
 	    fprintf(stderr, "%s: read error %ld "
f76dca
@@ -494,14 +493,6 @@ on_client_connection(uv_stream_t *stream
f76dca
     handle->data = (void *)proxy;
f76dca
     client->proxy = proxy;
f76dca
 
f76dca
-    /* insert client into doubly-linked list at the head */
f76dca
-    uv_mutex_lock(&proxy->mutex);
f76dca
-    if ((client->next = proxy->first) != NULL)
f76dca
-	proxy->first->prev = &client->next;
f76dca
-    proxy->first = client;
f76dca
-    client->prev = &proxy->first;
f76dca
-    uv_mutex_unlock(&proxy->mutex);
f76dca
-
f76dca
     status = uv_read_start((uv_stream_t *)&client->stream.u.tcp,
f76dca
 			    on_buffer_alloc, on_client_read);
f76dca
     if (status != 0) {
f76dca
@@ -719,7 +710,7 @@ shutdown_ports(void *arg)
f76dca
     struct proxy	*proxy = (struct proxy *)arg;
f76dca
     struct server	*server;
f76dca
     struct stream	*stream;
f76dca
-    int			i;
f76dca
+    unsigned int	i;
f76dca
 
f76dca
     for (i = 0; i < proxy->nservers; i++) {
f76dca
 	server = &proxy->servers[i];
f76dca
@@ -756,7 +747,8 @@ dump_request_ports(FILE *output, void *a
f76dca
     struct proxy	*proxy = (struct proxy *)arg;
f76dca
     struct stream	*stream;
f76dca
     uv_os_fd_t		uv_fd;
f76dca
-    int			i, fd;
f76dca
+    unsigned int	i;
f76dca
+    int			fd;
f76dca
 
f76dca
     fprintf(output, "%s request port(s):\n"
f76dca
 		"  sts fd   port  family address\n"
f76dca
diff -Naurp pcp-5.3.5.orig/src/pmproxy/src/server.h pcp-5.3.5/src/pmproxy/src/server.h
f76dca
--- pcp-5.3.5.orig/src/pmproxy/src/server.h	2021-09-24 09:33:06.000000000 +1000
f76dca
+++ pcp-5.3.5/src/pmproxy/src/server.h	2021-12-09 11:22:09.830321401 +1100
f76dca
@@ -1,5 +1,5 @@
f76dca
 /*
f76dca
- * Copyright (c) 2018-2019 Red Hat.
f76dca
+ * Copyright (c) 2018-2019,2021 Red Hat.
f76dca
  *
f76dca
  * This program is free software; you can redistribute it and/or modify it
f76dca
  * under the terms of the GNU Lesser General Public License as published
f76dca
@@ -97,11 +97,11 @@ typedef struct http_client {
f76dca
 
f76dca
 typedef struct pcp_client {
f76dca
     pcp_proxy_state_t	state;
f76dca
-    sds			hostname;
f76dca
     unsigned int	port : 16;
f76dca
     unsigned int	certreq : 1;
f76dca
     unsigned int	connected : 1;
f76dca
     unsigned int	pad : 14;
f76dca
+    sds			hostname;
f76dca
     uv_connect_t	pmcd;
f76dca
     uv_tcp_t		socket;
f76dca
 } pcp_client_t;
f76dca
@@ -136,8 +136,6 @@ typedef struct client {
f76dca
 	pcp_client_t	pcp;
f76dca
     } u;
f76dca
     struct proxy	*proxy;
f76dca
-    struct client	*next;
f76dca
-    struct client	**prev;
f76dca
     sds			buffer;
f76dca
 } client_t;
f76dca
 
f76dca
@@ -161,7 +159,7 @@ typedef struct proxy {
f76dca
     struct dict		*config;	/* configuration dictionary */
f76dca
     uv_loop_t		*events;	/* global, async event loop */
f76dca
     uv_callback_t	write_callbacks;
f76dca
-    uv_mutex_t		mutex;		/* protects client lists and pending writes */
f76dca
+    uv_mutex_t		write_mutex;	/* protects pending writes */
f76dca
 } proxy_t;
f76dca
 
f76dca
 extern void proxylog(pmLogLevel, sds, void *);