[Pkg-postgresql-public] Bug#678858: postgresql-8.4: install fails on ipv6-only system
Christoph Berg
myon at debian.org
Sun Jul 8 21:39:39 UTC 2012
Re: Daniel Kahn Gillmor 2012-07-08 <4FF9DD62.10205 at fifthhorseman.net>
> On 07/08/2012 11:57 AM, Christoph Berg wrote:
> > I can't really test it here because the Debian (linux) kernels have
> > ipv4 compiled in.
>
> You might be able to test it on a debian machine by not even bringing up
> the loopback interface with ipv4 -- i ran into this problem a while ago
> on a machine running stock debian (including the kernel), and subscribed
> to it, so i'm pretty sure it's replicable without a custom kernel.
I tried that when I realized I couldn't just "rmmod ipv4", but
"ifconfig lo down" will just make 127.0.0.1 disappear, but the
socket() call will still succeed. Later I realized I could test it in
the code by removing the ipv4 call.
You might have run into some other problem, postgres' stats collector
wants to open a UDP socket on localhost, but that will work for ipv6
as well, as long as there's some ipv6 "localhost" entry in /etc/hosts.
(I believe it is not fatal for that not to work, though.)
net.ipv6.bindv6only makes things even more interesting, so I rewrote
the test to try both protocols, and only allocate a port if it is free
for all protocols that are available.
--- PgCommon.pm 2012-04-10 09:19:24 +0000
+++ PgCommon.pm 2012-07-08 21:30:50 +0000
@@ -1,6 +1,7 @@
# Common functions for the postgresql-common framework
#
# (C) 2008-2009 Martin Pitt <mpitt at debian.org>
+# (C) 2012 Christoph Berg <myon at debian.org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -15,6 +16,7 @@
package PgCommon;
use strict;
use Socket;
+use Socket qw(IN6ADDR_ANY);
use POSIX;
use Exporter;
@@ -670,18 +672,30 @@
}
my $port;
- for ($port = $defaultport; ; ++$port) {
+ for ($port = $defaultport; $port < 65536; ++$port) {
next if grep { $_ == $port } @ports;
# check if port is already in use
- socket (SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or
+ my ($have_ip4, $res4, $have_ip6, $res6);
+ if (socket (SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'))) { # IPv4
+ $have_ip4 = 1;
+ $res4 = bind (SOCK, sockaddr_in($port, INADDR_ANY));
+ }
+ if (socket (SOCK, PF_INET6, SOCK_STREAM, getprotobyname('tcp'))) { # IPv6
+ $have_ip6 = 1;
+ $res6 = bind (SOCK, sockaddr_in6($port, IN6ADDR_ANY));
+ }
+ unless ($have_ip4 or $have_ip6) {
+ # require at least one protocol to work (PostgreSQL needs it anyway
+ # for the stats collector)
die "could not create socket: $!";
- my $res = bind (SOCK, sockaddr_in($port, INADDR_ANY));
+ }
close SOCK;
- last if $res;
+ # return port if it is available on all supported protocols
+ return $port if ($have_ip4 ? $res4 : 1) and ($have_ip6 ? $res6 : 1);
}
- return $port;
+ die "no free port found";
}
# Return the PostgreSQL version, cluster, and database to connect to. version
Christoph
--
cb at df7cb.de | http://www.df7cb.de/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.alioth.debian.org/pipermail/pkg-postgresql-public/attachments/20120708/e78dd9ba/attachment.pgp>
More information about the Pkg-postgresql-public
mailing list