Blame SOURCES/redhat-bugzilla-2030140.patch

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