Re: GSSENC'ed connection stalls while reconnection attempts. - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | Re: GSSENC'ed connection stalls while reconnection attempts. |
Date | |
Msg-id | 2460502.1594510912@sss.pgh.pa.us Whole thread Raw |
In response to | Re: GSSENC'ed connection stalls while reconnection attempts. (Tom Lane <tgl@sss.pgh.pa.us>) |
List | pgsql-hackers |
I wrote: > Kyotaro Horiguchi <horikyota.ntt@gmail.com> writes: >> If psql connected using GSSAPI auth and server restarted, reconnection >> sequence stalls and won't return. > Yeah, reproduced here. (I wonder if there's any reasonable way to > exercise this scenario in src/test/kerberos/.) I tried writing such a test based on the IO::Pty infrastructure used by src/bin/psql/t/010_tab_completion.pl, as attached. It works, but it feels pretty grotty, especially seeing that so much of the patch is copy-and-pasted from 010_tab_completion.pl. I think if we want to have a test like this, it'd be good to work a little harder on refactoring so that more of that code can be shared. My Perl skillz are a bit weak for that, though. regards, tom lane diff --git a/src/test/kerberos/t/001_auth.pl b/src/test/kerberos/t/001_auth.pl index b3aeea9574..552d2724e7 100644 --- a/src/test/kerberos/t/001_auth.pl +++ b/src/test/kerberos/t/001_auth.pl @@ -13,17 +13,30 @@ use strict; use warnings; + use TestLib; use PostgresNode; use Test::More; +use IPC::Run qw(pump finish timer); +use Data::Dumper; -if ($ENV{with_gssapi} eq 'yes') +# Do nothing unless Makefile has told us that the build is --with-gssapi. +if ($ENV{with_gssapi} ne 'yes') { + plan skip_all => 'GSSAPI/Kerberos not supported by this build'; +} + +# If we don't have IO::Pty, we can't run the test with interactive_psql. +my $have_pty = 1; +eval { require IO::Pty; }; +if ($@) +{ + $have_pty = 0; plan tests => 18; } else { - plan skip_all => 'GSSAPI/Kerberos not supported by this build'; + plan tests => 22; } my ($krb5_bin_dir, $krb5_sbin_dir); @@ -275,6 +288,77 @@ test_query( "gssencmode=require", "sending 100K lines works"); +# Test that libpq can reconnect after a server restart. +if ($have_pty) +{ + # fire up an interactive psql session + my $in = ''; + my $out = ''; + + my $timer = timer(5); + + my $h = $node->interactive_psql( + 'postgres', + \$in, + \$out, + $timer, + extra_params => [ + '-XAtd', + $node->connstr('postgres') + . " host=$host hostaddr=$hostaddr gssencmode=require user=test1" + ]); + + like( + $out, + qr/GSSAPI-encrypted connection/, + "startup banner shows GSSAPI encryption"); + + # subroutine to send a command and wait for response + sub interactive_command + { + my ($send, $pattern, $annotation) = @_; + + # report test failures from caller location + local $Test::Builder::Level = $Test::Builder::Level + 1; + + # reset output collector + $out = ""; + # restart per-command timer + $timer->start(5); + # send the data to be sent + $in .= $send; + # wait ... + pump $h until ($out =~ $pattern || $timer->is_expired); + my $okay = ($out =~ $pattern && !$timer->is_expired); + ok($okay, $annotation); + # for debugging, log actual output if it didn't match + local $Data::Dumper::Terse = 1; + local $Data::Dumper::Useqq = 1; + diag 'Actual output was ' + . Dumper($out) + . "Did not match \"$pattern\"\n" + if !$okay; + return; + } + + interactive_command("SELECT 2+2;\n", qr/4/, "interactive psql is alive"); + + $node->restart; + + interactive_command( + "SELECT 2+2;\n", + qr/The connection to the server was lost.*GSSAPI-encrypted connection/s, + "startup banner shows GSSAPI encryption after reconnection"); + + interactive_command("SELECT 20+22;\n", qr/42/, "psql is still alive"); + + # send psql an explicit \q to shut it down, else pty won't close properly + $timer->start(5); + $in .= "\\q\n"; + finish $h or die "psql returned $?"; + $timer->reset; +} + unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', qq{hostgssenc all all $hostaddr/32 gss map=mymap});
pgsql-hackers by date: