Skip to content

Commit 8a65ebb

Browse files
committed
Fix an OverflowError in readline_channel and enhance timeout handling
1 parent 94e4211 commit 8a65ebb

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

kubernetes/base/stream/ws_client.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ def read_channel(self, channel, timeout=0):
8989

9090
def readline_channel(self, channel, timeout=None):
9191
"""Read a line from a channel."""
92-
if timeout is None:
93-
timeout = float("inf")
92+
if timeout is not None and timeout < 0:
93+
timeout = None
9494
start = time.time()
95-
while self.is_open() and time.time() - start < timeout:
95+
while timeout is None or time.time() - start < timeout:
9696
if channel in self._channels:
9797
data = self._channels[channel]
9898
if self.newline in data:
@@ -104,7 +104,15 @@ def readline_channel(self, channel, timeout=None):
104104
else:
105105
del self._channels[channel]
106106
return ret
107-
self.update(timeout=(timeout - time.time() + start))
107+
108+
if not self.is_open():
109+
return
110+
111+
if timeout is not None:
112+
# the timeout here should never be negative, because otherwise this method could block indefinitly
113+
self.update(timeout=max(timeout - time.time() + start, 0))
114+
else:
115+
self.update(timeout=None)
108116

109117
def write_channel(self, channel, data):
110118
"""Write data to a channel."""
@@ -190,6 +198,13 @@ def update(self, timeout=0):
190198
r = poll.poll(timeout)
191199
poll.unregister(self.sock.sock)
192200
else:
201+
# select.select() does not work with negative timeouts, when a negative value is
202+
# given select.epoll() and select.poll() are blocking until there is an event for
203+
# the poll object, therefore set the timeout to None in order to have the same
204+
# behaviour when select.select() is used
205+
if timeout is not None and timeout < 0:
206+
timeout = None
207+
193208
r, _, _ = select.select(
194209
(self.sock.sock, ), (), (), timeout)
195210

@@ -220,10 +235,11 @@ def update(self, timeout=0):
220235
def run_forever(self, timeout=None):
221236
"""Wait till connection is closed or timeout reached. Buffer any input
222237
received during this time."""
223-
if timeout:
238+
if timeout is not None:
224239
start = time.time()
225240
while self.is_open() and time.time() - start < timeout:
226-
self.update(timeout=(timeout - time.time() + start))
241+
# the timeout here should never be negative, because otherwise this method could block indefinitly
242+
self.update(timeout=max(timeout - time.time() + start, 0))
227243
else:
228244
while self.is_open():
229245
self.update(timeout=None)

kubernetes/e2e_test/test_client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ def test_pod_apis(self):
157157
line = resp.readline_stderr(timeout=5)
158158
self.assertFalse(resp.peek_stdout())
159159
self.assertEqual("test string 2", line)
160+
resp.write_stdin("sleep 2 && echo test string 3\n")
161+
line = resp.readline_stdout(timeout=5)
162+
self.assertEqual("test string 3", line)
163+
resp.write_stdin("sleep 5 && echo test string 4\n")
164+
line = resp.readline_stdout(timeout=0)
165+
self.assertIsNone(line)
166+
line = resp.readline_stdout(timeout=-1)
167+
self.assertEqual("test string 4", line)
160168
resp.write_stdin("exit\n")
161169
resp.update(timeout=5)
162170
while True:

0 commit comments

Comments
 (0)