On Sat, Aug 3, 2019 at 3:30 PM Zac Medico <zmed...@gentoo.org> wrote:
>
> Add _has_ipv6() function and use it in _configure_loopback_interface()
> to decide whether to add an IPv6 address.
>
> Bug: https://bugs.gentoo.org/691290
> ---
>  lib/portage/process.py | 40 +++++++++++++++++++++++++++++++++++++---
>  1 file changed, 37 insertions(+), 3 deletions(-)
>
> diff --git a/lib/portage/process.py b/lib/portage/process.py
> index 690421815..ca8b0c172 100644
> --- a/lib/portage/process.py
> +++ b/lib/portage/process.py
> @@ -339,6 +339,9 @@ def spawn(mycommand, env=None, opt_name=None, 
> fd_pipes=None, returnpid=False,
>                 fd_pipes[1] = pw
>                 fd_pipes[2] = pw
>
> +       # Cache _has_ipv6() result for use in child processes.
> +       _has_ipv6()
> +
>         # This caches the libc library lookup and _unshare_validator results
>         # in the current process, so that results are cached for use in
>         # child processes.
> @@ -446,6 +449,38 @@ def spawn(mycommand, env=None, opt_name=None, 
> fd_pipes=None, returnpid=False,
>         # Everything succeeded
>         return 0
>
> +__has_ipv6 = None
> +
> +def _has_ipv6():
> +       """
> +       Test that both userland and kernel support IPv6, by attempting
> +       to create a socket and listen on any unused port of the IPv6
> +       ::1 loopback address.
> +
> +       @rtype: bool
> +       @return: True if IPv6 is supported, False otherwise.
> +       """
> +       global __has_ipv6
> +
> +       if __has_ipv6 is None:
> +               if socket.has_ipv6:
> +                       sock = None
> +                       try:
> +                               # python2.7 sockets do not support context 
> management protocol
> +                               sock = socket.socket(socket.AF_INET6, 
> socket.SOCK_DGRAM)
> +                               sock.bind(('::1', 0))
> +                       except EnvironmentError:
> +                               __has_ipv6 = False
> +                       else:
> +                               __has_ipv6 = True
> +                       finally:
> +                               if sock is not None:
> +                                       sock.close()
> +               else:
> +                       __has_ipv6 = False
> +
> +       return __has_ipv6
> +
>  def _configure_loopback_interface():
>         """
>         Configure the loopback interface.
> @@ -478,9 +513,8 @@ def _configure_loopback_interface():
>
>         try:
>                 subprocess.call(['ip', 'address', 'add', '10.0.0.1/8', 'dev', 
> 'lo'])
> -               with open(os.devnull, 'wb', 0) as devnull:
> -                       subprocess.call(['ip', 'address', 'add', 'fd00::1/8', 
> 'dev', 'lo'],
> -                               stdout=devnull, stderr=devnull)
> +               if _has_ipv6():
> +                       subprocess.call(['ip', 'address', 'add', 'fd00::1/8', 
> 'dev', 'lo'])
>         except EnvironmentError as e:
>                 writemsg("Error calling 'ip': %s\n" % e.strerror, 
> noiselevel=-1)
>
> --
> 2.21.0
>

This seems reasonable, though I don't have an IPv6-less system to test it on.

Reply via email to