Skip to content

Commit 2ec760a

Browse files
committed
Fix an OverflowError in readline_channel and enhance timeout handling
1 parent 84f5fea commit 2ec760a

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
@@ -86,10 +86,10 @@ def read_channel(self, channel, timeout=0):
8686

8787
def readline_channel(self, channel, timeout=None):
8888
"""Read a line from a channel."""
89-
if timeout is None:
90-
timeout = float("inf")
89+
if timeout is not None and timeout < 0:
90+
timeout = None
9191
start = time.time()
92-
while self.is_open() and time.time() - start < timeout:
92+
while timeout is None or time.time() - start < timeout:
9393
if channel in self._channels:
9494
data = self._channels[channel]
9595
if "\n" in data:
@@ -101,7 +101,15 @@ def readline_channel(self, channel, timeout=None):
101101
else:
102102
del self._channels[channel]
103103
return ret
104-
self.update(timeout=(timeout - time.time() + start))
104+
105+
if not self.is_open():
106+
return
107+
108+
if timeout is not None:
109+
# the timeout here should never be negative, because otherwise this method could block indefinitly
110+
self.update(timeout=max(timeout - time.time() + start, 0))
111+
else:
112+
self.update(timeout=None)
105113

106114
def write_channel(self, channel, data):
107115
"""Write data to a channel."""
@@ -187,6 +195,13 @@ def update(self, timeout=0):
187195
r = poll.poll(timeout)
188196
poll.unregister(self.sock.sock)
189197
else:
198+
# select.select() does not work with negative timeouts, when a negative value is
199+
# given select.epoll() and select.poll() are blocking until there is an event for
200+
# the poll object, therefore set the timeout to None in order to have the same
201+
# behaviour when select.select() is used
202+
if timeout is not None and timeout < 0:
203+
timeout = None
204+
190205
r, _, _ = select.select(
191206
(self.sock.sock, ), (), (), timeout)
192207

@@ -215,10 +230,11 @@ def update(self, timeout=0):
215230
def run_forever(self, timeout=None):
216231
"""Wait till connection is closed or timeout reached. Buffer any input
217232
received during this time."""
218-
if timeout:
233+
if timeout is not None:
219234
start = time.time()
220235
while self.is_open() and time.time() - start < timeout:
221-
self.update(timeout=(timeout - time.time() + start))
236+
# the timeout here should never be negative, because otherwise this method could block indefinitly
237+
self.update(timeout=max(timeout - time.time() + start, 0))
222238
else:
223239
while self.is_open():
224240
self.update(timeout=None)

kubernetes/e2e_test/test_client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ def test_pod_apis(self):
142142
line = resp.readline_stderr(timeout=5)
143143
self.assertFalse(resp.peek_stdout())
144144
self.assertEqual("test string 2", line)
145+
resp.write_stdin("sleep 2 && echo test string 3\n")
146+
line = resp.readline_stdout(timeout=5)
147+
self.assertEqual("test string 3", line)
148+
resp.write_stdin("sleep 5 && echo test string 4\n")
149+
line = resp.readline_stdout(timeout=0)
150+
self.assertIsNone(line)
151+
line = resp.readline_stdout(timeout=-1)
152+
self.assertEqual("test string 4", line)
145153
resp.write_stdin("exit\n")
146154
resp.update(timeout=5)
147155
while True:

0 commit comments

Comments
 (0)