We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
exec_run: filedescriptor out of range in select() (python3)
The following code works with python2, but throws error on python3:
```
import docker

files = [open('/tmp/test_' + str(i), 'w+b') for i in range(0, 1024)]
client = docker.from_env()
cnt = client.containers.run("ubuntu:18.04", command="sleep 10", detach=True, auto_remove=True)
cnt.exec_run("ls -ls")
```
Output: 
```  File "var/dockerpy_bug.py", line 6, in <module>
    cnt.exec_run("ls -ls")
  File "/usr/lib/python3/dist-packages/docker/models/containers.py", line 185, in exec_run
    resp['Id'], detach=detach, tty=tty, stream=stream, socket=socket
  File "/usr/lib/python3/dist-packages/docker/utils/decorators.py", line 19, in wrapped
    return f(self, resource_id, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/docker/api/exec_api.py", line 165, in exec_start
    return self._read_from_socket(res, stream, tty)
  File "/usr/lib/python3/dist-packages/docker/api/client.py", line 377, in _read_from_socket
    return six.binary_type().join(gen)
  File "/usr/lib/python3/dist-packages/docker/utils/socket.py", line 75, in frames_iter
    n = next_frame_size(socket)
  File "/usr/lib/python3/dist-packages/docker/utils/socket.py", line 62, in next_frame_size
    data = read_exactly(socket, 8)
  File "/usr/lib/python3/dist-packages/docker/utils/socket.py", line 47, in read_exactly
    next_data = read(socket, n - len(data))
  File "/usr/lib/python3/dist-packages/docker/utils/socket.py", line 27, in read
    select.select([socket], [], [])
ValueError: filedescriptor out of range in select()
```
if socket has fd > 1024, select will fail
Stack Overflow suggests using poll() in place of select(), as it's not bound by 1024 fd limit.

Environment :
ubuntu: 18.04
docker: 18.09.3
docker API: 1.39
python: 3.6.7
docker-py: 3.7.0

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docker/utils/socket.py`
Content:
```
1 import errno
2 import os
3 import select
4 import socket as pysocket
5 import struct
6 
7 try:
8     from ..transport import NpipeSocket
9 except ImportError:
10     NpipeSocket = type(None)
11 
12 
13 STDOUT = 1
14 STDERR = 2
15 
16 
17 class SocketError(Exception):
18     pass
19 
20 
21 # NpipeSockets have their own error types
22 # pywintypes.error: (109, 'ReadFile', 'The pipe has been ended.')
23 NPIPE_ENDED = 109
24 
25 
26 def read(socket, n=4096):
27     """
28     Reads at most n bytes from socket
29     """
30 
31     recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)
32 
33     if not isinstance(socket, NpipeSocket):
34         select.select([socket], [], [])
35 
36     try:
37         if hasattr(socket, 'recv'):
38             return socket.recv(n)
39         if isinstance(socket, getattr(pysocket, 'SocketIO')):
40             return socket.read(n)
41         return os.read(socket.fileno(), n)
42     except OSError as e:
43         if e.errno not in recoverable_errors:
44             raise
45     except Exception as e:
46         is_pipe_ended = (isinstance(socket, NpipeSocket) and
47                          len(e.args) > 0 and
48                          e.args[0] == NPIPE_ENDED)
49         if is_pipe_ended:
50             # npipes don't support duplex sockets, so we interpret
51             # a PIPE_ENDED error as a close operation (0-length read).
52             return ''
53         raise
54 
55 
56 def read_exactly(socket, n):
57     """
58     Reads exactly n bytes from socket
59     Raises SocketError if there isn't enough data
60     """
61     data = bytes()
62     while len(data) < n:
63         next_data = read(socket, n - len(data))
64         if not next_data:
65             raise SocketError("Unexpected EOF")
66         data += next_data
67     return data
68 
69 
70 def next_frame_header(socket):
71     """
72     Returns the stream and size of the next frame of data waiting to be read
73     from socket, according to the protocol defined here:
74 
75     https://docs.docker.com/engine/api/v1.24/#attach-to-a-container
76     """
77     try:
78         data = read_exactly(socket, 8)
79     except SocketError:
80         return (-1, -1)
81 
82     stream, actual = struct.unpack('>BxxxL', data)
83     return (stream, actual)
84 
85 
86 def frames_iter(socket, tty):
87     """
88     Return a generator of frames read from socket. A frame is a tuple where
89     the first item is the stream number and the second item is a chunk of data.
90 
91     If the tty setting is enabled, the streams are multiplexed into the stdout
92     stream.
93     """
94     if tty:
95         return ((STDOUT, frame) for frame in frames_iter_tty(socket))
96     else:
97         return frames_iter_no_tty(socket)
98 
99 
100 def frames_iter_no_tty(socket):
101     """
102     Returns a generator of data read from the socket when the tty setting is
103     not enabled.
104     """
105     while True:
106         (stream, n) = next_frame_header(socket)
107         if n < 0:
108             break
109         while n > 0:
110             result = read(socket, n)
111             if result is None:
112                 continue
113             data_length = len(result)
114             if data_length == 0:
115                 # We have reached EOF
116                 return
117             n -= data_length
118             yield (stream, result)
119 
120 
121 def frames_iter_tty(socket):
122     """
123     Return a generator of data read from the socket when the tty setting is
124     enabled.
125     """
126     while True:
127         result = read(socket)
128         if len(result) == 0:
129             # We have reached EOF
130             return
131         yield result
132 
133 
134 def consume_socket_output(frames, demux=False):
135     """
136     Iterate through frames read from the socket and return the result.
137 
138     Args:
139 
140         demux (bool):
141             If False, stdout and stderr are multiplexed, and the result is the
142             concatenation of all the frames. If True, the streams are
143             demultiplexed, and the result is a 2-tuple where each item is the
144             concatenation of frames belonging to the same stream.
145     """
146     if demux is False:
147         # If the streams are multiplexed, the generator returns strings, that
148         # we just need to concatenate.
149         return bytes().join(frames)
150 
151     # If the streams are demultiplexed, the generator yields tuples
152     # (stdout, stderr)
153     out = [None, None]
154     for frame in frames:
155         # It is guaranteed that for each frame, one and only one stream
156         # is not None.
157         assert frame != (None, None)
158         if frame[0] is not None:
159             if out[0] is None:
160                 out[0] = frame[0]
161             else:
162                 out[0] += frame[0]
163         else:
164             if out[1] is None:
165                 out[1] = frame[1]
166             else:
167                 out[1] += frame[1]
168     return tuple(out)
169 
170 
171 def demux_adaptor(stream_id, data):
172     """
173     Utility to demultiplex stdout and stderr when reading frames from the
174     socket.
175     """
176     if stream_id == STDOUT:
177         return (data, None)
178     elif stream_id == STDERR:
179         return (None, data)
180     else:
181         raise ValueError(f'{stream_id} is not a valid stream')
182
```
--- 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/docker/utils/socket.py b/docker/utils/socket.py
--- a/docker/utils/socket.py
+++ b/docker/utils/socket.py
@@ -3,6 +3,7 @@
 import select
 import socket as pysocket
 import struct
+import sys
 
 try:
     from ..transport import NpipeSocket
@@ -31,7 +32,13 @@
     recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)
 
     if not isinstance(socket, NpipeSocket):
-        select.select([socket], [], [])
+        if sys.platform == 'win32':
+            # Limited to 1024
+            select.select([socket], [], [])
+        else:
+            poll = select.poll()
+            poll.register(socket)
+            poll.poll()
 
     try:
         if hasattr(socket, 'recv'):

{"golden_diff": "diff --git a/docker/utils/socket.py b/docker/utils/socket.py\n--- a/docker/utils/socket.py\n+++ b/docker/utils/socket.py\n@@ -3,6 +3,7 @@\n import select\n import socket as pysocket\n import struct\n+import sys\n \n try:\n     from ..transport import NpipeSocket\n@@ -31,7 +32,13 @@\n     recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)\n \n     if not isinstance(socket, NpipeSocket):\n-        select.select([socket], [], [])\n+        if sys.platform == 'win32':\n+            # Limited to 1024\n+            select.select([socket], [], [])\n+        else:\n+            poll = select.poll()\n+            poll.register(socket)\n+            poll.poll()\n \n     try:\n         if hasattr(socket, 'recv'):\n", "issue": "exec_run: filedescriptor out of range in select() (python3)\nThe following code works with python2, but throws error on python3:\r\n```\r\nimport docker\r\n\r\nfiles = [open('/tmp/test_' + str(i), 'w+b') for i in range(0, 1024)]\r\nclient = docker.from_env()\r\ncnt = client.containers.run(\"ubuntu:18.04\", command=\"sleep 10\", detach=True, auto_remove=True)\r\ncnt.exec_run(\"ls -ls\")\r\n```\r\nOutput: \r\n```  File \"var/dockerpy_bug.py\", line 6, in <module>\r\n    cnt.exec_run(\"ls -ls\")\r\n  File \"/usr/lib/python3/dist-packages/docker/models/containers.py\", line 185, in exec_run\r\n    resp['Id'], detach=detach, tty=tty, stream=stream, socket=socket\r\n  File \"/usr/lib/python3/dist-packages/docker/utils/decorators.py\", line 19, in wrapped\r\n    return f(self, resource_id, *args, **kwargs)\r\n  File \"/usr/lib/python3/dist-packages/docker/api/exec_api.py\", line 165, in exec_start\r\n    return self._read_from_socket(res, stream, tty)\r\n  File \"/usr/lib/python3/dist-packages/docker/api/client.py\", line 377, in _read_from_socket\r\n    return six.binary_type().join(gen)\r\n  File \"/usr/lib/python3/dist-packages/docker/utils/socket.py\", line 75, in frames_iter\r\n    n = next_frame_size(socket)\r\n  File \"/usr/lib/python3/dist-packages/docker/utils/socket.py\", line 62, in next_frame_size\r\n    data = read_exactly(socket, 8)\r\n  File \"/usr/lib/python3/dist-packages/docker/utils/socket.py\", line 47, in read_exactly\r\n    next_data = read(socket, n - len(data))\r\n  File \"/usr/lib/python3/dist-packages/docker/utils/socket.py\", line 27, in read\r\n    select.select([socket], [], [])\r\nValueError: filedescriptor out of range in select()\r\n```\r\nif socket has fd > 1024, select will fail\r\nStack Overflow suggests using poll() in place of select(), as it's not bound by 1024 fd limit.\r\n\r\nEnvironment :\r\nubuntu: 18.04\r\ndocker: 18.09.3\r\ndocker API: 1.39\r\npython: 3.6.7\r\ndocker-py: 3.7.0\n", "before_files": [{"content": "import errno\nimport os\nimport select\nimport socket as pysocket\nimport struct\n\ntry:\n    from ..transport import NpipeSocket\nexcept ImportError:\n    NpipeSocket = type(None)\n\n\nSTDOUT = 1\nSTDERR = 2\n\n\nclass SocketError(Exception):\n    pass\n\n\n# NpipeSockets have their own error types\n# pywintypes.error: (109, 'ReadFile', 'The pipe has been ended.')\nNPIPE_ENDED = 109\n\n\ndef read(socket, n=4096):\n    \"\"\"\n    Reads at most n bytes from socket\n    \"\"\"\n\n    recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)\n\n    if not isinstance(socket, NpipeSocket):\n        select.select([socket], [], [])\n\n    try:\n        if hasattr(socket, 'recv'):\n            return socket.recv(n)\n        if isinstance(socket, getattr(pysocket, 'SocketIO')):\n            return socket.read(n)\n        return os.read(socket.fileno(), n)\n    except OSError as e:\n        if e.errno not in recoverable_errors:\n            raise\n    except Exception as e:\n        is_pipe_ended = (isinstance(socket, NpipeSocket) and\n                         len(e.args) > 0 and\n                         e.args[0] == NPIPE_ENDED)\n        if is_pipe_ended:\n            # npipes don't support duplex sockets, so we interpret\n            # a PIPE_ENDED error as a close operation (0-length read).\n            return ''\n        raise\n\n\ndef read_exactly(socket, n):\n    \"\"\"\n    Reads exactly n bytes from socket\n    Raises SocketError if there isn't enough data\n    \"\"\"\n    data = bytes()\n    while len(data) < n:\n        next_data = read(socket, n - len(data))\n        if not next_data:\n            raise SocketError(\"Unexpected EOF\")\n        data += next_data\n    return data\n\n\ndef next_frame_header(socket):\n    \"\"\"\n    Returns the stream and size of the next frame of data waiting to be read\n    from socket, according to the protocol defined here:\n\n    https://docs.docker.com/engine/api/v1.24/#attach-to-a-container\n    \"\"\"\n    try:\n        data = read_exactly(socket, 8)\n    except SocketError:\n        return (-1, -1)\n\n    stream, actual = struct.unpack('>BxxxL', data)\n    return (stream, actual)\n\n\ndef frames_iter(socket, tty):\n    \"\"\"\n    Return a generator of frames read from socket. A frame is a tuple where\n    the first item is the stream number and the second item is a chunk of data.\n\n    If the tty setting is enabled, the streams are multiplexed into the stdout\n    stream.\n    \"\"\"\n    if tty:\n        return ((STDOUT, frame) for frame in frames_iter_tty(socket))\n    else:\n        return frames_iter_no_tty(socket)\n\n\ndef frames_iter_no_tty(socket):\n    \"\"\"\n    Returns a generator of data read from the socket when the tty setting is\n    not enabled.\n    \"\"\"\n    while True:\n        (stream, n) = next_frame_header(socket)\n        if n < 0:\n            break\n        while n > 0:\n            result = read(socket, n)\n            if result is None:\n                continue\n            data_length = len(result)\n            if data_length == 0:\n                # We have reached EOF\n                return\n            n -= data_length\n            yield (stream, result)\n\n\ndef frames_iter_tty(socket):\n    \"\"\"\n    Return a generator of data read from the socket when the tty setting is\n    enabled.\n    \"\"\"\n    while True:\n        result = read(socket)\n        if len(result) == 0:\n            # We have reached EOF\n            return\n        yield result\n\n\ndef consume_socket_output(frames, demux=False):\n    \"\"\"\n    Iterate through frames read from the socket and return the result.\n\n    Args:\n\n        demux (bool):\n            If False, stdout and stderr are multiplexed, and the result is the\n            concatenation of all the frames. If True, the streams are\n            demultiplexed, and the result is a 2-tuple where each item is the\n            concatenation of frames belonging to the same stream.\n    \"\"\"\n    if demux is False:\n        # If the streams are multiplexed, the generator returns strings, that\n        # we just need to concatenate.\n        return bytes().join(frames)\n\n    # If the streams are demultiplexed, the generator yields tuples\n    # (stdout, stderr)\n    out = [None, None]\n    for frame in frames:\n        # It is guaranteed that for each frame, one and only one stream\n        # is not None.\n        assert frame != (None, None)\n        if frame[0] is not None:\n            if out[0] is None:\n                out[0] = frame[0]\n            else:\n                out[0] += frame[0]\n        else:\n            if out[1] is None:\n                out[1] = frame[1]\n            else:\n                out[1] += frame[1]\n    return tuple(out)\n\n\ndef demux_adaptor(stream_id, data):\n    \"\"\"\n    Utility to demultiplex stdout and stderr when reading frames from the\n    socket.\n    \"\"\"\n    if stream_id == STDOUT:\n        return (data, None)\n    elif stream_id == STDERR:\n        return (None, data)\n    else:\n        raise ValueError(f'{stream_id} is not a valid stream')\n", "path": "docker/utils/socket.py"}], "after_files": [{"content": "import errno\nimport os\nimport select\nimport socket as pysocket\nimport struct\nimport sys\n\ntry:\n    from ..transport import NpipeSocket\nexcept ImportError:\n    NpipeSocket = type(None)\n\n\nSTDOUT = 1\nSTDERR = 2\n\n\nclass SocketError(Exception):\n    pass\n\n\n# NpipeSockets have their own error types\n# pywintypes.error: (109, 'ReadFile', 'The pipe has been ended.')\nNPIPE_ENDED = 109\n\n\ndef read(socket, n=4096):\n    \"\"\"\n    Reads at most n bytes from socket\n    \"\"\"\n\n    recoverable_errors = (errno.EINTR, errno.EDEADLK, errno.EWOULDBLOCK)\n\n    if not isinstance(socket, NpipeSocket):\n        if sys.platform == 'win32':\n            # Limited to 1024\n            select.select([socket], [], [])\n        else:\n            poll = select.poll()\n            poll.register(socket)\n            poll.poll()\n\n    try:\n        if hasattr(socket, 'recv'):\n            return socket.recv(n)\n        if isinstance(socket, getattr(pysocket, 'SocketIO')):\n            return socket.read(n)\n        return os.read(socket.fileno(), n)\n    except OSError as e:\n        if e.errno not in recoverable_errors:\n            raise\n    except Exception as e:\n        is_pipe_ended = (isinstance(socket, NpipeSocket) and\n                         len(e.args) > 0 and\n                         e.args[0] == NPIPE_ENDED)\n        if is_pipe_ended:\n            # npipes don't support duplex sockets, so we interpret\n            # a PIPE_ENDED error as a close operation (0-length read).\n            return ''\n        raise\n\n\ndef read_exactly(socket, n):\n    \"\"\"\n    Reads exactly n bytes from socket\n    Raises SocketError if there isn't enough data\n    \"\"\"\n    data = bytes()\n    while len(data) < n:\n        next_data = read(socket, n - len(data))\n        if not next_data:\n            raise SocketError(\"Unexpected EOF\")\n        data += next_data\n    return data\n\n\ndef next_frame_header(socket):\n    \"\"\"\n    Returns the stream and size of the next frame of data waiting to be read\n    from socket, according to the protocol defined here:\n\n    https://docs.docker.com/engine/api/v1.24/#attach-to-a-container\n    \"\"\"\n    try:\n        data = read_exactly(socket, 8)\n    except SocketError:\n        return (-1, -1)\n\n    stream, actual = struct.unpack('>BxxxL', data)\n    return (stream, actual)\n\n\ndef frames_iter(socket, tty):\n    \"\"\"\n    Return a generator of frames read from socket. A frame is a tuple where\n    the first item is the stream number and the second item is a chunk of data.\n\n    If the tty setting is enabled, the streams are multiplexed into the stdout\n    stream.\n    \"\"\"\n    if tty:\n        return ((STDOUT, frame) for frame in frames_iter_tty(socket))\n    else:\n        return frames_iter_no_tty(socket)\n\n\ndef frames_iter_no_tty(socket):\n    \"\"\"\n    Returns a generator of data read from the socket when the tty setting is\n    not enabled.\n    \"\"\"\n    while True:\n        (stream, n) = next_frame_header(socket)\n        if n < 0:\n            break\n        while n > 0:\n            result = read(socket, n)\n            if result is None:\n                continue\n            data_length = len(result)\n            if data_length == 0:\n                # We have reached EOF\n                return\n            n -= data_length\n            yield (stream, result)\n\n\ndef frames_iter_tty(socket):\n    \"\"\"\n    Return a generator of data read from the socket when the tty setting is\n    enabled.\n    \"\"\"\n    while True:\n        result = read(socket)\n        if len(result) == 0:\n            # We have reached EOF\n            return\n        yield result\n\n\ndef consume_socket_output(frames, demux=False):\n    \"\"\"\n    Iterate through frames read from the socket and return the result.\n\n    Args:\n\n        demux (bool):\n            If False, stdout and stderr are multiplexed, and the result is the\n            concatenation of all the frames. If True, the streams are\n            demultiplexed, and the result is a 2-tuple where each item is the\n            concatenation of frames belonging to the same stream.\n    \"\"\"\n    if demux is False:\n        # If the streams are multiplexed, the generator returns strings, that\n        # we just need to concatenate.\n        return bytes().join(frames)\n\n    # If the streams are demultiplexed, the generator yields tuples\n    # (stdout, stderr)\n    out = [None, None]\n    for frame in frames:\n        # It is guaranteed that for each frame, one and only one stream\n        # is not None.\n        assert frame != (None, None)\n        if frame[0] is not None:\n            if out[0] is None:\n                out[0] = frame[0]\n            else:\n                out[0] += frame[0]\n        else:\n            if out[1] is None:\n                out[1] = frame[1]\n            else:\n                out[1] += frame[1]\n    return tuple(out)\n\n\ndef demux_adaptor(stream_id, data):\n    \"\"\"\n    Utility to demultiplex stdout and stderr when reading frames from the\n    socket.\n    \"\"\"\n    if stream_id == STDOUT:\n        return (data, None)\n    elif stream_id == STDERR:\n        return (None, data)\n    else:\n        raise ValueError(f'{stream_id} is not a valid stream')\n", "path": "docker/utils/socket.py"}]}