[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