From 10afde0a2105511fbf17b5f5223b7e6ca2f3136d Mon Sep 17 00:00:00 2001
From: "suyu.cmj" <mengjuan.cmj@alibaba-inc.com>
Date: Mon, 6 Sep 2021 07:20:17 +0000
Subject: [PATCH] Add test for backend process gets stuck on secure_write and
 can not be canceled

---
 src/test/perl/PostgresNode.pm                    | 27 +++++++++++++
 src/test/recovery/t/000_stuck_on_secure_write.pl | 49 ++++++++++++++++++++++++
 2 files changed, 76 insertions(+)
 create mode 100644 src/test/recovery/t/000_stuck_on_secure_write.pl

diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm
index c59da75..b6a158a 100644
--- a/src/test/perl/PostgresNode.pm
+++ b/src/test/perl/PostgresNode.pm
@@ -844,6 +844,33 @@ sub start
 
 =pod
 
+=item $node->find_child(process_name)
+Get child pid by process_name
+=cut
+sub find_child
+{
+	my ($self, $process_name) = @_;
+	my $pid=0;
+	my @childs=`ps -o pid,cmd --ppid $self->{_pid}` or die "can't run ps! $! \n";
+
+	foreach my $child (@childs)
+	{
+		$child =~ s/^\s+|\s+$//g;
+		my $pos = index($child, $process_name);
+		if ($pos > 0)
+		{
+			$pos = index($child, ' ');
+			$pid = substr($child, 0, $pos);
+			$pid =~ s/^\s+|\s+$//g;
+			last;
+		}
+	}
+
+	return $pid;
+}
+
+=pod
+
 =item $node->kill9()
 
 Send SIGKILL (signal 9) to the postmaster.
diff --git a/src/test/recovery/t/000_stuck_on_secure_write.pl b/src/test/recovery/t/000_stuck_on_secure_write.pl
new file mode 100644
index 0000000..cc37734
--- /dev/null
+++ b/src/test/recovery/t/000_stuck_on_secure_write.pl
@@ -0,0 +1,49 @@
+# Test for backend process gets stuck on secure_write()
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib ();
+use Test::More tests=>4;
+
+# primary node
+my $node_primary = PostgresNode->new('primary');
+$node_primary->init;
+
+$node_primary->start;
+$node_primary->safe_psql('postgres', 'CREATE TABLE test_table(val integer);');
+# insert more data so that the output buffer can be filled up when select from the table
+$node_primary->safe_psql('postgres', "INSERT INTO test_table(val) SELECT generate_series(1,5000000) as newwal");
+
+my $connstr = $node_primary->connstr;
+my @res = `nohup psql -d "$connstr" -c "begin; select pg_sleep(5); select * from test_table;" > myout.file 2>&1 &`;
+my $client = readpipe("ps -ef | grep \"select pg_sleep(5)\" | grep -v grep | awk '{print \$2}'");
+print "client pid: $client";
+ok($client != 0, "ready to stop client");
+
+# stop client and backend process will get stuck on secure_write()
+sleep 3;
+@res = `kill -stop $client`;
+my $pid = $node_primary->find_child("[local] SELECT");
+print "backend pid:$pid\n";
+ok($pid != 0, "get corresponding backend process");
+
+# cancel the query
+sleep 10;
+$node_primary->safe_psql('postgres', "select pg_cancel_backend($pid)");
+# check the query
+sleep 3;
+my $pid_new = $node_primary->find_child("[local] SELECT");
+print "backend pid:$pid_new\n";
+ok($pid_new == $pid, "backend can't be canceled");
+
+# cancel the query again
+$node_primary->safe_psql('postgres', "select :($pid)");
+# check the query
+sleep 3;
+$pid_new = $node_primary->find_child("[local] SELECT");
+print "backend pid:$pid_new\n";
+ok($pid_new == $pid, "backend can't be canceled");
+
+# sleep to check the backtrace of backend process by pstack backend_pid
+sleep 300;
+$node_primary->stop;
\ No newline at end of file
-- 
1.8.3.1

