Blame SOURCES/redhat-bugzilla-2030140.patch

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