We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
serve_tcp() fails out-of-the-box on systems with disabled IPv6
I recently had occasion to run a Trio server on a Linux system that had `ipv6.disable=1` in the kernel command line. I don't know why it was configured this way, but some Googling suggests that this is not such a very uncommon configuration. In this configuration, `getaddrinfo(None, ...)` still returns an IPv6 option, but `socket(AF_INET6, ...)` fails with `[Errno 97] Address family not supported by protocol`. This also affects several tests in trio's test suite.

I can work around this by explicitly serving on `"0.0.0.0"`, but it feels like a rough edge. As an alternative, maybe trio could suppress `EAFNOSUPPORT` errors from IPv6 socket creation in `open_tcp_listeners` if the IPv4 socket was created OK. Thoughts?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `trio/_highlevel_open_tcp_listeners.py`
Content:
```
1 import sys
2 from math import inf
3 
4 import trio
5 from . import socket as tsocket
6 
7 __all__ = ["open_tcp_listeners", "serve_tcp"]
8 
9 
10 # Default backlog size:
11 #
12 # Having the backlog too low can cause practical problems (a perfectly healthy
13 # service that starts failing to accept connections if they arrive in a
14 # burst).
15 #
16 # Having it too high doesn't really cause any problems. Like any buffer, you
17 # want backlog queue to be zero usually, and it won't save you if you're
18 # getting connection attempts faster than you can call accept() on an ongoing
19 # basis. But unlike other buffers, this one doesn't really provide any
20 # backpressure. If a connection gets stuck waiting in the backlog queue, then
21 # from the peer's point of view the connection succeeded but then their
22 # send/recv will stall until we get to it, possibly for a long time. OTOH if
23 # there isn't room in the backlog queue... then their connect stalls, possibly
24 # for a long time, which is pretty much the same thing.
25 #
26 # A large backlog can also use a bit more kernel memory, but this seems fairly
27 # negligible these days.
28 #
29 # So this suggests we should make the backlog as large as possible. This also
30 # matches what Golang does. However, they do it in a weird way, where they
31 # have a bunch of code to sniff out the configured upper limit for backlog on
32 # different operating systems. But on every system, passing in a too-large
33 # backlog just causes it to be silently truncated to the configured maximum,
34 # so this is unnecessary -- we can just pass in "infinity" and get the maximum
35 # that way. (Verified on Windows, Linux, macOS using
36 # notes-to-self/measure-listen-backlog.py)
37 def _compute_backlog(backlog):
38     if backlog is None:
39         backlog = inf
40     # Many systems (Linux, BSDs, ...) store the backlog in a uint16 and are
41     # missing overflow protection, so we apply our own overflow protection.
42     # https://github.com/golang/go/issues/5030
43     return min(backlog, 0xffff)
44 
45 
46 async def open_tcp_listeners(port, *, host=None, backlog=None):
47     """Create :class:`SocketListener` objects to listen for TCP connections.
48 
49     Args:
50 
51       port (int): The port to listen on.
52 
53           If you use 0 as your port, then the kernel will automatically pick
54           an arbitrary open port. But be careful: if you use this feature when
55           binding to multiple IP addresses, then each IP address will get its
56           own random port, and the returned listeners will probably be
57           listening on different ports. In particular, this will happen if you
58           use ``host=None`` – which is the default – because in this case
59           :func:`open_tcp_listeners` will bind to both the IPv4 wildcard
60           address (``0.0.0.0``) and also the IPv6 wildcard address (``::``).
61 
62       host (str, bytes-like, or None): The local interface to bind to. This is
63           passed to :func:`~socket.getaddrinfo` with the ``AI_PASSIVE`` flag
64           set.
65 
66           If you want to bind to the wildcard address on both IPv4 and IPv6,
67           in order to accept connections on all available interfaces, then
68           pass ``None``. This is the default.
69 
70           If you have a specific interface you want to bind to, pass its IP
71           address or hostname here. If a hostname resolves to multiple IP
72           addresses, this function will open one listener on each of them.
73 
74           If you want to use only IPv4, or only IPv6, but want to accept on
75           all interfaces, pass the family-specific wildcard address:
76           ``"0.0.0.0"`` for IPv4-only and ``"::"`` for IPv6-only.
77 
78       backlog (int or None): The listen backlog to use. If you leave this as
79           ``None`` then Trio will pick a good default. (Currently: whatever
80           your system has configured as the maximum backlog.)
81 
82     Returns:
83       list of :class:`SocketListener`
84 
85     """
86     # getaddrinfo sometimes allows port=None, sometimes not (depending on
87     # whether host=None). And on some systems it treats "" as 0, others it
88     # doesn't:
89     #   http://klickverbot.at/blog/2012/01/getaddrinfo-edge-case-behavior-on-windows-linux-and-osx/
90     if not isinstance(port, int):
91         raise TypeError("port must be an int or str, not {!r}".format(port))
92 
93     backlog = _compute_backlog(backlog)
94 
95     addresses = await tsocket.getaddrinfo(
96         host,
97         port,
98         type=tsocket.SOCK_STREAM,
99         flags=tsocket.AI_PASSIVE,
100     )
101 
102     listeners = []
103     try:
104         for family, type, proto, _, sockaddr in addresses:
105             sock = tsocket.socket(family, type, proto)
106             try:
107                 # See https://github.com/python-trio/trio/issues/39
108                 if sys.platform == "win32":
109                     sock.setsockopt(
110                         tsocket.SOL_SOCKET, tsocket.SO_EXCLUSIVEADDRUSE, 1
111                     )
112                 else:
113                     sock.setsockopt(
114                         tsocket.SOL_SOCKET, tsocket.SO_REUSEADDR, 1
115                     )
116 
117                 if family == tsocket.AF_INET6:
118                     sock.setsockopt(
119                         tsocket.IPPROTO_IPV6, tsocket.IPV6_V6ONLY, 1
120                     )
121 
122                 await sock.bind(sockaddr)
123                 sock.listen(backlog)
124 
125                 listeners.append(trio.SocketListener(sock))
126             except:
127                 sock.close()
128                 raise
129     except:
130         for listener in listeners:
131             listener.socket.close()
132         raise
133 
134     return listeners
135 
136 
137 async def serve_tcp(
138     handler,
139     port,
140     *,
141     host=None,
142     backlog=None,
143     handler_nursery=None,
144     task_status=trio.TASK_STATUS_IGNORED
145 ):
146     """Listen for incoming TCP connections, and for each one start a task
147     running ``handler(stream)``.
148 
149     This is a thin convenience wrapper around :func:`open_tcp_listeners` and
150     :func:`serve_listeners` – see them for full details.
151 
152     .. warning::
153 
154        If ``handler`` raises an exception, then this function doesn't do
155        anything special to catch it – so by default the exception will
156        propagate out and crash your server. If you don't want this, then catch
157        exceptions inside your ``handler``, or use a ``handler_nursery`` object
158        that responds to exceptions in some other way.
159 
160     When used with ``nursery.start`` you get back the newly opened listeners.
161     So, for example, if you want to start a server in your test suite and then
162     connect to it to check that it's working properly, you can use something
163     like::
164 
165         from trio.testing import open_stream_to_socket_listener
166 
167         async with trio.open_nursery() as nursery:
168             listeners = await nursery.start(serve_tcp, handler, 0)
169             client_stream = await open_stream_to_socket_listener(listeners[0])
170 
171             # Then send and receive data on 'client_stream', for example:
172             await client_stream.send_all(b"GET / HTTP/1.0\\r\\n\\r\\n")
173 
174     This avoids several common pitfalls:
175 
176     1. It lets the kernel pick a random open port, so your test suite doesn't
177        depend on any particular port being open.
178 
179     2. It waits for the server to be accepting connections on that port before
180        ``start`` returns, so there's no race condition where the incoming
181        connection arrives before the server is ready.
182 
183     3. It uses the Listener object to find out which port was picked, so it
184        can connect to the right place.
185 
186     Args:
187       handler: The handler to start for each incoming connection. Passed to
188           :func:`serve_listeners`.
189 
190       port: The port to listen on. Use 0 to let the kernel pick an open port.
191           Passed to :func:`open_tcp_listeners`.
192 
193       host (str, bytes, or None): The host interface to listen on; use
194           ``None`` to bind to the wildcard address. Passed to
195           :func:`open_tcp_listeners`.
196 
197       backlog: The listen backlog, or None to have a good default picked.
198           Passed to :func:`open_tcp_listeners`.
199 
200       handler_nursery: The nursery to start handlers in, or None to use an
201           internal nursery. Passed to :func:`serve_listeners`.
202 
203       task_status: This function can be used with ``nursery.start``.
204 
205     Returns:
206       This function only returns when cancelled.
207 
208     """
209     listeners = await trio.open_tcp_listeners(port, host=host, backlog=backlog)
210     await trio.serve_listeners(
211         handler,
212         listeners,
213         handler_nursery=handler_nursery,
214         task_status=task_status
215     )
216
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/trio/_highlevel_open_tcp_listeners.py b/trio/_highlevel_open_tcp_listeners.py
--- a/trio/_highlevel_open_tcp_listeners.py
+++ b/trio/_highlevel_open_tcp_listeners.py
@@ -1,3 +1,4 @@
+import errno
 import sys
 from math import inf
 
@@ -100,9 +101,23 @@
     )
 
     listeners = []
+    unsupported_address_families = []
     try:
         for family, type, proto, _, sockaddr in addresses:
-            sock = tsocket.socket(family, type, proto)
+            try:
+                sock = tsocket.socket(family, type, proto)
+            except OSError as ex:
+                if ex.errno == errno.EAFNOSUPPORT:
+                    # If a system only supports IPv4, or only IPv6, it
+                    # is still likely that getaddrinfo will return
+                    # both an IPv4 and an IPv6 address. As long as at
+                    # least one of the returned addresses can be
+                    # turned into a socket, we won't complain about a
+                    # failure to create the other.
+                    unsupported_address_families.append(ex)
+                    continue
+                else:
+                    raise
             try:
                 # See https://github.com/python-trio/trio/issues/39
                 if sys.platform == "win32":
@@ -131,6 +146,13 @@
             listener.socket.close()
         raise
 
+    if unsupported_address_families and not listeners:
+        raise OSError(
+            errno.EAFNOSUPPORT,
+            "This system doesn't support any of the kinds of "
+            "socket that that address could use"
+        ) from trio.MultiError(unsupported_address_families)
+
     return listeners

{"golden_diff": "diff --git a/trio/_highlevel_open_tcp_listeners.py b/trio/_highlevel_open_tcp_listeners.py\n--- a/trio/_highlevel_open_tcp_listeners.py\n+++ b/trio/_highlevel_open_tcp_listeners.py\n@@ -1,3 +1,4 @@\n+import errno\n import sys\n from math import inf\n \n@@ -100,9 +101,23 @@\n     )\n \n     listeners = []\n+    unsupported_address_families = []\n     try:\n         for family, type, proto, _, sockaddr in addresses:\n-            sock = tsocket.socket(family, type, proto)\n+            try:\n+                sock = tsocket.socket(family, type, proto)\n+            except OSError as ex:\n+                if ex.errno == errno.EAFNOSUPPORT:\n+                    # If a system only supports IPv4, or only IPv6, it\n+                    # is still likely that getaddrinfo will return\n+                    # both an IPv4 and an IPv6 address. As long as at\n+                    # least one of the returned addresses can be\n+                    # turned into a socket, we won't complain about a\n+                    # failure to create the other.\n+                    unsupported_address_families.append(ex)\n+                    continue\n+                else:\n+                    raise\n             try:\n                 # See https://github.com/python-trio/trio/issues/39\n                 if sys.platform == \"win32\":\n@@ -131,6 +146,13 @@\n             listener.socket.close()\n         raise\n \n+    if unsupported_address_families and not listeners:\n+        raise OSError(\n+            errno.EAFNOSUPPORT,\n+            \"This system doesn't support any of the kinds of \"\n+            \"socket that that address could use\"\n+        ) from trio.MultiError(unsupported_address_families)\n+\n     return listeners\n", "issue": "serve_tcp() fails out-of-the-box on systems with disabled IPv6\nI recently had occasion to run a Trio server on a Linux system that had `ipv6.disable=1` in the kernel command line. I don't know why it was configured this way, but some Googling suggests that this is not such a very uncommon configuration. In this configuration, `getaddrinfo(None, ...)` still returns an IPv6 option, but `socket(AF_INET6, ...)` fails with `[Errno 97] Address family not supported by protocol`. This also affects several tests in trio's test suite.\r\n\r\nI can work around this by explicitly serving on `\"0.0.0.0\"`, but it feels like a rough edge. As an alternative, maybe trio could suppress `EAFNOSUPPORT` errors from IPv6 socket creation in `open_tcp_listeners` if the IPv4 socket was created OK. Thoughts?\n", "before_files": [{"content": "import sys\nfrom math import inf\n\nimport trio\nfrom . import socket as tsocket\n\n__all__ = [\"open_tcp_listeners\", \"serve_tcp\"]\n\n\n# Default backlog size:\n#\n# Having the backlog too low can cause practical problems (a perfectly healthy\n# service that starts failing to accept connections if they arrive in a\n# burst).\n#\n# Having it too high doesn't really cause any problems. Like any buffer, you\n# want backlog queue to be zero usually, and it won't save you if you're\n# getting connection attempts faster than you can call accept() on an ongoing\n# basis. But unlike other buffers, this one doesn't really provide any\n# backpressure. If a connection gets stuck waiting in the backlog queue, then\n# from the peer's point of view the connection succeeded but then their\n# send/recv will stall until we get to it, possibly for a long time. OTOH if\n# there isn't room in the backlog queue... then their connect stalls, possibly\n# for a long time, which is pretty much the same thing.\n#\n# A large backlog can also use a bit more kernel memory, but this seems fairly\n# negligible these days.\n#\n# So this suggests we should make the backlog as large as possible. This also\n# matches what Golang does. However, they do it in a weird way, where they\n# have a bunch of code to sniff out the configured upper limit for backlog on\n# different operating systems. But on every system, passing in a too-large\n# backlog just causes it to be silently truncated to the configured maximum,\n# so this is unnecessary -- we can just pass in \"infinity\" and get the maximum\n# that way. (Verified on Windows, Linux, macOS using\n# notes-to-self/measure-listen-backlog.py)\ndef _compute_backlog(backlog):\n    if backlog is None:\n        backlog = inf\n    # Many systems (Linux, BSDs, ...) store the backlog in a uint16 and are\n    # missing overflow protection, so we apply our own overflow protection.\n    # https://github.com/golang/go/issues/5030\n    return min(backlog, 0xffff)\n\n\nasync def open_tcp_listeners(port, *, host=None, backlog=None):\n    \"\"\"Create :class:`SocketListener` objects to listen for TCP connections.\n\n    Args:\n\n      port (int): The port to listen on.\n\n          If you use 0 as your port, then the kernel will automatically pick\n          an arbitrary open port. But be careful: if you use this feature when\n          binding to multiple IP addresses, then each IP address will get its\n          own random port, and the returned listeners will probably be\n          listening on different ports. In particular, this will happen if you\n          use ``host=None`` \u2013 which is the default \u2013 because in this case\n          :func:`open_tcp_listeners` will bind to both the IPv4 wildcard\n          address (``0.0.0.0``) and also the IPv6 wildcard address (``::``).\n\n      host (str, bytes-like, or None): The local interface to bind to. This is\n          passed to :func:`~socket.getaddrinfo` with the ``AI_PASSIVE`` flag\n          set.\n\n          If you want to bind to the wildcard address on both IPv4 and IPv6,\n          in order to accept connections on all available interfaces, then\n          pass ``None``. This is the default.\n\n          If you have a specific interface you want to bind to, pass its IP\n          address or hostname here. If a hostname resolves to multiple IP\n          addresses, this function will open one listener on each of them.\n\n          If you want to use only IPv4, or only IPv6, but want to accept on\n          all interfaces, pass the family-specific wildcard address:\n          ``\"0.0.0.0\"`` for IPv4-only and ``\"::\"`` for IPv6-only.\n\n      backlog (int or None): The listen backlog to use. If you leave this as\n          ``None`` then Trio will pick a good default. (Currently: whatever\n          your system has configured as the maximum backlog.)\n\n    Returns:\n      list of :class:`SocketListener`\n\n    \"\"\"\n    # getaddrinfo sometimes allows port=None, sometimes not (depending on\n    # whether host=None). And on some systems it treats \"\" as 0, others it\n    # doesn't:\n    #   http://klickverbot.at/blog/2012/01/getaddrinfo-edge-case-behavior-on-windows-linux-and-osx/\n    if not isinstance(port, int):\n        raise TypeError(\"port must be an int or str, not {!r}\".format(port))\n\n    backlog = _compute_backlog(backlog)\n\n    addresses = await tsocket.getaddrinfo(\n        host,\n        port,\n        type=tsocket.SOCK_STREAM,\n        flags=tsocket.AI_PASSIVE,\n    )\n\n    listeners = []\n    try:\n        for family, type, proto, _, sockaddr in addresses:\n            sock = tsocket.socket(family, type, proto)\n            try:\n                # See https://github.com/python-trio/trio/issues/39\n                if sys.platform == \"win32\":\n                    sock.setsockopt(\n                        tsocket.SOL_SOCKET, tsocket.SO_EXCLUSIVEADDRUSE, 1\n                    )\n                else:\n                    sock.setsockopt(\n                        tsocket.SOL_SOCKET, tsocket.SO_REUSEADDR, 1\n                    )\n\n                if family == tsocket.AF_INET6:\n                    sock.setsockopt(\n                        tsocket.IPPROTO_IPV6, tsocket.IPV6_V6ONLY, 1\n                    )\n\n                await sock.bind(sockaddr)\n                sock.listen(backlog)\n\n                listeners.append(trio.SocketListener(sock))\n            except:\n                sock.close()\n                raise\n    except:\n        for listener in listeners:\n            listener.socket.close()\n        raise\n\n    return listeners\n\n\nasync def serve_tcp(\n    handler,\n    port,\n    *,\n    host=None,\n    backlog=None,\n    handler_nursery=None,\n    task_status=trio.TASK_STATUS_IGNORED\n):\n    \"\"\"Listen for incoming TCP connections, and for each one start a task\n    running ``handler(stream)``.\n\n    This is a thin convenience wrapper around :func:`open_tcp_listeners` and\n    :func:`serve_listeners` \u2013 see them for full details.\n\n    .. warning::\n\n       If ``handler`` raises an exception, then this function doesn't do\n       anything special to catch it \u2013 so by default the exception will\n       propagate out and crash your server. If you don't want this, then catch\n       exceptions inside your ``handler``, or use a ``handler_nursery`` object\n       that responds to exceptions in some other way.\n\n    When used with ``nursery.start`` you get back the newly opened listeners.\n    So, for example, if you want to start a server in your test suite and then\n    connect to it to check that it's working properly, you can use something\n    like::\n\n        from trio.testing import open_stream_to_socket_listener\n\n        async with trio.open_nursery() as nursery:\n            listeners = await nursery.start(serve_tcp, handler, 0)\n            client_stream = await open_stream_to_socket_listener(listeners[0])\n\n            # Then send and receive data on 'client_stream', for example:\n            await client_stream.send_all(b\"GET / HTTP/1.0\\\\r\\\\n\\\\r\\\\n\")\n\n    This avoids several common pitfalls:\n\n    1. It lets the kernel pick a random open port, so your test suite doesn't\n       depend on any particular port being open.\n\n    2. It waits for the server to be accepting connections on that port before\n       ``start`` returns, so there's no race condition where the incoming\n       connection arrives before the server is ready.\n\n    3. It uses the Listener object to find out which port was picked, so it\n       can connect to the right place.\n\n    Args:\n      handler: The handler to start for each incoming connection. Passed to\n          :func:`serve_listeners`.\n\n      port: The port to listen on. Use 0 to let the kernel pick an open port.\n          Passed to :func:`open_tcp_listeners`.\n\n      host (str, bytes, or None): The host interface to listen on; use\n          ``None`` to bind to the wildcard address. Passed to\n          :func:`open_tcp_listeners`.\n\n      backlog: The listen backlog, or None to have a good default picked.\n          Passed to :func:`open_tcp_listeners`.\n\n      handler_nursery: The nursery to start handlers in, or None to use an\n          internal nursery. Passed to :func:`serve_listeners`.\n\n      task_status: This function can be used with ``nursery.start``.\n\n    Returns:\n      This function only returns when cancelled.\n\n    \"\"\"\n    listeners = await trio.open_tcp_listeners(port, host=host, backlog=backlog)\n    await trio.serve_listeners(\n        handler,\n        listeners,\n        handler_nursery=handler_nursery,\n        task_status=task_status\n    )\n", "path": "trio/_highlevel_open_tcp_listeners.py"}], "after_files": [{"content": "import errno\nimport sys\nfrom math import inf\n\nimport trio\nfrom . import socket as tsocket\n\n__all__ = [\"open_tcp_listeners\", \"serve_tcp\"]\n\n\n# Default backlog size:\n#\n# Having the backlog too low can cause practical problems (a perfectly healthy\n# service that starts failing to accept connections if they arrive in a\n# burst).\n#\n# Having it too high doesn't really cause any problems. Like any buffer, you\n# want backlog queue to be zero usually, and it won't save you if you're\n# getting connection attempts faster than you can call accept() on an ongoing\n# basis. But unlike other buffers, this one doesn't really provide any\n# backpressure. If a connection gets stuck waiting in the backlog queue, then\n# from the peer's point of view the connection succeeded but then their\n# send/recv will stall until we get to it, possibly for a long time. OTOH if\n# there isn't room in the backlog queue... then their connect stalls, possibly\n# for a long time, which is pretty much the same thing.\n#\n# A large backlog can also use a bit more kernel memory, but this seems fairly\n# negligible these days.\n#\n# So this suggests we should make the backlog as large as possible. This also\n# matches what Golang does. However, they do it in a weird way, where they\n# have a bunch of code to sniff out the configured upper limit for backlog on\n# different operating systems. But on every system, passing in a too-large\n# backlog just causes it to be silently truncated to the configured maximum,\n# so this is unnecessary -- we can just pass in \"infinity\" and get the maximum\n# that way. (Verified on Windows, Linux, macOS using\n# notes-to-self/measure-listen-backlog.py)\ndef _compute_backlog(backlog):\n    if backlog is None:\n        backlog = inf\n    # Many systems (Linux, BSDs, ...) store the backlog in a uint16 and are\n    # missing overflow protection, so we apply our own overflow protection.\n    # https://github.com/golang/go/issues/5030\n    return min(backlog, 0xffff)\n\n\nasync def open_tcp_listeners(port, *, host=None, backlog=None):\n    \"\"\"Create :class:`SocketListener` objects to listen for TCP connections.\n\n    Args:\n\n      port (int): The port to listen on.\n\n          If you use 0 as your port, then the kernel will automatically pick\n          an arbitrary open port. But be careful: if you use this feature when\n          binding to multiple IP addresses, then each IP address will get its\n          own random port, and the returned listeners will probably be\n          listening on different ports. In particular, this will happen if you\n          use ``host=None`` \u2013 which is the default \u2013 because in this case\n          :func:`open_tcp_listeners` will bind to both the IPv4 wildcard\n          address (``0.0.0.0``) and also the IPv6 wildcard address (``::``).\n\n      host (str, bytes-like, or None): The local interface to bind to. This is\n          passed to :func:`~socket.getaddrinfo` with the ``AI_PASSIVE`` flag\n          set.\n\n          If you want to bind to the wildcard address on both IPv4 and IPv6,\n          in order to accept connections on all available interfaces, then\n          pass ``None``. This is the default.\n\n          If you have a specific interface you want to bind to, pass its IP\n          address or hostname here. If a hostname resolves to multiple IP\n          addresses, this function will open one listener on each of them.\n\n          If you want to use only IPv4, or only IPv6, but want to accept on\n          all interfaces, pass the family-specific wildcard address:\n          ``\"0.0.0.0\"`` for IPv4-only and ``\"::\"`` for IPv6-only.\n\n      backlog (int or None): The listen backlog to use. If you leave this as\n          ``None`` then Trio will pick a good default. (Currently: whatever\n          your system has configured as the maximum backlog.)\n\n    Returns:\n      list of :class:`SocketListener`\n\n    \"\"\"\n    # getaddrinfo sometimes allows port=None, sometimes not (depending on\n    # whether host=None). And on some systems it treats \"\" as 0, others it\n    # doesn't:\n    #   http://klickverbot.at/blog/2012/01/getaddrinfo-edge-case-behavior-on-windows-linux-and-osx/\n    if not isinstance(port, int):\n        raise TypeError(\"port must be an int or str, not {!r}\".format(port))\n\n    backlog = _compute_backlog(backlog)\n\n    addresses = await tsocket.getaddrinfo(\n        host,\n        port,\n        type=tsocket.SOCK_STREAM,\n        flags=tsocket.AI_PASSIVE,\n    )\n\n    listeners = []\n    unsupported_address_families = []\n    try:\n        for family, type, proto, _, sockaddr in addresses:\n            try:\n                sock = tsocket.socket(family, type, proto)\n            except OSError as ex:\n                if ex.errno == errno.EAFNOSUPPORT:\n                    # If a system only supports IPv4, or only IPv6, it\n                    # is still likely that getaddrinfo will return\n                    # both an IPv4 and an IPv6 address. As long as at\n                    # least one of the returned addresses can be\n                    # turned into a socket, we won't complain about a\n                    # failure to create the other.\n                    unsupported_address_families.append(ex)\n                    continue\n                else:\n                    raise\n            try:\n                # See https://github.com/python-trio/trio/issues/39\n                if sys.platform == \"win32\":\n                    sock.setsockopt(\n                        tsocket.SOL_SOCKET, tsocket.SO_EXCLUSIVEADDRUSE, 1\n                    )\n                else:\n                    sock.setsockopt(\n                        tsocket.SOL_SOCKET, tsocket.SO_REUSEADDR, 1\n                    )\n\n                if family == tsocket.AF_INET6:\n                    sock.setsockopt(\n                        tsocket.IPPROTO_IPV6, tsocket.IPV6_V6ONLY, 1\n                    )\n\n                await sock.bind(sockaddr)\n                sock.listen(backlog)\n\n                listeners.append(trio.SocketListener(sock))\n            except:\n                sock.close()\n                raise\n    except:\n        for listener in listeners:\n            listener.socket.close()\n        raise\n\n    if unsupported_address_families and not listeners:\n        raise OSError(\n            errno.EAFNOSUPPORT,\n            \"This system doesn't support any of the kinds of \"\n            \"socket that that address could use\"\n        ) from trio.MultiError(unsupported_address_families)\n\n    return listeners\n\n\nasync def serve_tcp(\n    handler,\n    port,\n    *,\n    host=None,\n    backlog=None,\n    handler_nursery=None,\n    task_status=trio.TASK_STATUS_IGNORED\n):\n    \"\"\"Listen for incoming TCP connections, and for each one start a task\n    running ``handler(stream)``.\n\n    This is a thin convenience wrapper around :func:`open_tcp_listeners` and\n    :func:`serve_listeners` \u2013 see them for full details.\n\n    .. warning::\n\n       If ``handler`` raises an exception, then this function doesn't do\n       anything special to catch it \u2013 so by default the exception will\n       propagate out and crash your server. If you don't want this, then catch\n       exceptions inside your ``handler``, or use a ``handler_nursery`` object\n       that responds to exceptions in some other way.\n\n    When used with ``nursery.start`` you get back the newly opened listeners.\n    So, for example, if you want to start a server in your test suite and then\n    connect to it to check that it's working properly, you can use something\n    like::\n\n        from trio.testing import open_stream_to_socket_listener\n\n        async with trio.open_nursery() as nursery:\n            listeners = await nursery.start(serve_tcp, handler, 0)\n            client_stream = await open_stream_to_socket_listener(listeners[0])\n\n            # Then send and receive data on 'client_stream', for example:\n            await client_stream.send_all(b\"GET / HTTP/1.0\\\\r\\\\n\\\\r\\\\n\")\n\n    This avoids several common pitfalls:\n\n    1. It lets the kernel pick a random open port, so your test suite doesn't\n       depend on any particular port being open.\n\n    2. It waits for the server to be accepting connections on that port before\n       ``start`` returns, so there's no race condition where the incoming\n       connection arrives before the server is ready.\n\n    3. It uses the Listener object to find out which port was picked, so it\n       can connect to the right place.\n\n    Args:\n      handler: The handler to start for each incoming connection. Passed to\n          :func:`serve_listeners`.\n\n      port: The port to listen on. Use 0 to let the kernel pick an open port.\n          Passed to :func:`open_tcp_listeners`.\n\n      host (str, bytes, or None): The host interface to listen on; use\n          ``None`` to bind to the wildcard address. Passed to\n          :func:`open_tcp_listeners`.\n\n      backlog: The listen backlog, or None to have a good default picked.\n          Passed to :func:`open_tcp_listeners`.\n\n      handler_nursery: The nursery to start handlers in, or None to use an\n          internal nursery. Passed to :func:`serve_listeners`.\n\n      task_status: This function can be used with ``nursery.start``.\n\n    Returns:\n      This function only returns when cancelled.\n\n    \"\"\"\n    listeners = await trio.open_tcp_listeners(port, host=host, backlog=backlog)\n    await trio.serve_listeners(\n        handler,\n        listeners,\n        handler_nursery=handler_nursery,\n        task_status=task_status\n    )\n", "path": "trio/_highlevel_open_tcp_listeners.py"}]}