Skip to content

Commit 3a8ea81

Browse files
committed
aexpect: Use time.monotonic() for time-diff operations
to avoid problems with NTP (or iffy clock sources) let's use time.monotonic() for time difference operations. Signed-off-by: Lukáš Doktor <[email protected]>
1 parent f6985e5 commit 3a8ea81

File tree

5 files changed

+40
-40
lines changed

5 files changed

+40
-40
lines changed

aexpect/client.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ def _get_aexpect_helper(self, helper_cmd, pass_fds, echo, command):
266266
# Wait for the server to complete its initialization
267267
full_output = ""
268268
pattern = f"Server {self.a_id} ready"
269-
end_time = time.time() + 60
270-
while time.time() < end_time:
269+
end_time = time.monotonic() + 60
270+
while time.monotonic() < end_time:
271271
output = sub.stdout.readline().decode(self.encoding, "ignore")
272272
if pattern in output:
273273
break
@@ -896,7 +896,7 @@ def _read_nonblocking(self, internal_timeout=None, timeout=None):
896896
internal_timeout *= 1000
897897
end_time = None
898898
if timeout:
899-
end_time = time.time() + timeout
899+
end_time = time.monotonic() + timeout
900900
expect_pipe = self._get_fd("expect")
901901
poller = select.poll()
902902
poller.register(expect_pipe, select.POLLIN)
@@ -915,7 +915,7 @@ def _read_nonblocking(self, internal_timeout=None, timeout=None):
915915
data += raw_data.decode(self.encoding, "ignore")
916916
else:
917917
return read, data
918-
if end_time and time.time() > end_time:
918+
if end_time and time.monotonic() > end_time:
919919
return read, data
920920

921921
def read_nonblocking(self, internal_timeout=None, timeout=None):
@@ -1009,10 +1009,10 @@ def read_until_output_matches(
10091009
poller = select.poll()
10101010
poller.register(expect_pipe, select.POLLIN)
10111011
output = ""
1012-
end_time = time.time() + timeout
1012+
end_time = time.monotonic() + timeout
10131013
while True:
10141014
try:
1015-
max_ms = int((end_time - time.time()) * 1000)
1015+
max_ms = int((end_time - time.monotonic()) * 1000)
10161016
poll_timeout_ms = max(0, max_ms)
10171017
poll_status = poller.poll(poll_timeout_ms)
10181018
except select.error:
@@ -1021,7 +1021,7 @@ def read_until_output_matches(
10211021
raise ExpectTimeoutError(patterns, output)
10221022
# Read data from child
10231023
read, data = self._read_nonblocking(
1024-
internal_timeout, end_time - time.time()
1024+
internal_timeout, end_time - time.monotonic()
10251025
)
10261026
if not read:
10271027
break
@@ -1291,10 +1291,10 @@ def is_responsive(self, timeout=5.0):
12911291
# Send a newline
12921292
self.sendline()
12931293
# Wait up to timeout seconds for some output from the child
1294-
end_time = time.time() + timeout
1295-
while time.time() < end_time:
1294+
end_time = time.monotonic() + timeout
1295+
while time.monotonic() < end_time:
12961296
time.sleep(0.5)
1297-
if self.read_nonblocking(0, end_time - time.time()).strip():
1297+
if self.read_nonblocking(0, end_time - time.monotonic()).strip():
12981298
return True
12991299
# No output -- report unresponsive
13001300
return False
@@ -1414,8 +1414,8 @@ def cmd_output_safe(self, cmd, timeout=60, strip_console_codes=False):
14141414
self.sendline(cmd)
14151415
out = ""
14161416
success = False
1417-
start_time = time.time()
1418-
while (time.time() - start_time) < timeout:
1417+
start_time = time.monotonic()
1418+
while (time.monotonic() - start_time) < timeout:
14191419
try:
14201420
out += self.read_up_to_prompt(0.5)
14211421
success = True
@@ -1751,8 +1751,8 @@ def run_tail(
17511751
encoding=encoding,
17521752
)
17531753

1754-
end_time = time.time() + timeout
1755-
while time.time() < end_time and bg_process.is_alive():
1754+
end_time = time.monotonic() + timeout
1755+
while time.monotonic() < end_time and bg_process.is_alive():
17561756
time.sleep(0.1)
17571757

17581758
return bg_process
@@ -1804,8 +1804,8 @@ def run_bg(
18041804
encoding=encoding,
18051805
)
18061806

1807-
end_time = time.time() + timeout
1808-
while time.time() < end_time and bg_process.is_alive():
1807+
end_time = time.monotonic() + timeout
1808+
while time.monotonic() < end_time and bg_process.is_alive():
18091809
time.sleep(0.1)
18101810

18111811
return bg_process

aexpect/remote.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,9 @@ def wait_for_login(
532532
client,
533533
timeout,
534534
)
535-
end_time = time.time() + timeout
535+
end_time = time.monotonic() + timeout
536536
verbose = False
537-
while time.time() < end_time:
537+
while time.monotonic() < end_time:
538538
try:
539539
return remote_login(
540540
client,
@@ -1375,9 +1375,9 @@ def transfer(*args, **kwargs):
13751375
msg = f"Copy file from {args[0]}:{args[5]} to {args[6]}, "
13761376
else:
13771377
msg = f"Copy file from {args[5]} to {args[0]}:{args[6]}, "
1378-
start_time = time.time()
1378+
start_time = time.monotonic()
13791379
ret = func(*args, **kwargs)
1380-
elapsed_time = time.time() - start_time
1380+
elapsed_time = time.monotonic() - start_time
13811381
if kwargs.get("filesize", None) is not None:
13821382
throughput = kwargs["filesize"] / elapsed_time
13831383
msg += f"estimated throughput: {throughput:.2f} MB/s"

aexpect/rss_client.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def __init__(self, address, port, log_func=None, timeout=20):
143143
) from timeout_error
144144
self._send(struct.pack("=i", CHUNKSIZE))
145145
self._log_func = log_func
146-
self._last_time = time.time()
146+
self._last_time = time.monotonic()
147147
self._last_transferred = 0
148148
self.transferred = 0
149149

@@ -173,10 +173,10 @@ def _send(self, data, timeout=60):
173173

174174
def _receive(self, size, timeout=60):
175175
strs = []
176-
end_time = time.time() + timeout
176+
end_time = time.monotonic() + timeout
177177
try:
178178
while size > 0:
179-
timeout = end_time - time.time()
179+
timeout = end_time - time.monotonic()
180180
if timeout <= 0:
181181
raise socket.timeout
182182
self._socket.settimeout(timeout)
@@ -202,15 +202,15 @@ def _receive(self, size, timeout=60):
202202

203203
def _report_stats(self, data):
204204
if self._log_func:
205-
delta = time.time() - self._last_time
205+
delta = time.monotonic() - self._last_time
206206
if delta >= 1:
207207
transferred = self.transferred / 1048576.0
208208
speed = (self.transferred - self._last_transferred) / delta
209209
speed /= 1048576.0
210210
self._log_func(
211211
f"{data} {transferred:.3f} MB ({speed:.3f}" " MB/sec)"
212212
)
213-
self._last_time = time.time()
213+
self._last_time = time.monotonic()
214214
self._last_transferred = self.transferred
215215

216216
def _send_packet(self, data, timeout=60):
@@ -232,10 +232,10 @@ def _send_file_chunks(self, filename, timeout=60):
232232
self._log_func(f"Sending file {filename}")
233233
with open(filename, "rb") as file_handle:
234234
try:
235-
end_time = time.time() + timeout
235+
end_time = time.monotonic() + timeout
236236
while True:
237237
data = file_handle.read(CHUNKSIZE)
238-
self._send_packet(data, int(end_time - time.time()))
238+
self._send_packet(data, int(end_time - time.monotonic()))
239239
if len(data) < CHUNKSIZE:
240240
break
241241
except FileTransferError as error:
@@ -247,9 +247,9 @@ def _receive_file_chunks(self, filename, timeout=60):
247247
self._log_func(f"Receiving file {filename}")
248248
with open(filename, "wb") as file_handle:
249249
try:
250-
end_time = time.time() + timeout
250+
end_time = time.monotonic() + timeout
251251
while True:
252-
data = self._receive_packet(int(end_time - time.time()))
252+
data = self._receive_packet(int(end_time - time.monotonic()))
253253
file_handle.write(data)
254254
if len(data) < CHUNKSIZE:
255255
break
@@ -306,7 +306,7 @@ def _upload_file(self, path, end_time):
306306
if os.path.isfile(path):
307307
self._send_msg(RSS_CREATE_FILE)
308308
self._send_packet(os.path.basename(path).encode())
309-
self._send_file_chunks(path, end_time - time.time())
309+
self._send_file_chunks(path, end_time - time.monotonic())
310310
elif os.path.isdir(path):
311311
self._send_msg(RSS_CREATE_DIR)
312312
self._send_packet(os.path.basename(path).encode())
@@ -349,7 +349,7 @@ def upload(self, src_pattern, dst_path, timeout=600):
349349
message to the client
350350
:note: Other exceptions can be raised.
351351
"""
352-
end_time = time.time() + timeout
352+
end_time = time.monotonic() + timeout
353353
try:
354354
try:
355355
self._send_msg(RSS_SET_PATH)
@@ -371,7 +371,7 @@ def upload(self, src_pattern, dst_path, timeout=600):
371371
"or directories"
372372
)
373373
# Look for RSS_OK or RSS_ERROR
374-
msg = self._receive_msg(int(end_time - time.time()))
374+
msg = self._receive_msg(int(end_time - time.monotonic()))
375375
if msg == RSS_OK:
376376
return
377377
if msg == RSS_ERROR:
@@ -446,7 +446,7 @@ def download(self, src_pattern, dst_path, timeout=600):
446446
:note: Other exceptions can be raised.
447447
"""
448448
dst_path = os.path.abspath(dst_path)
449-
end_time = time.time() + timeout
449+
end_time = time.monotonic() + timeout
450450
file_count = 0
451451
dir_count = 0
452452
try:
@@ -463,7 +463,7 @@ def download(self, src_pattern, dst_path, timeout=600):
463463
if os.path.isdir(dst_path):
464464
dst_path = os.path.join(dst_path, filename)
465465
self._receive_file_chunks(
466-
dst_path, int(end_time - time.time())
466+
dst_path, int(end_time - time.monotonic())
467467
)
468468
dst_path = os.path.dirname(dst_path)
469469
file_count += 1

aexpect/shared.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ def get_lock_fd(filename, timeout=-1):
2929
lock_flags = fcntl.LOCK_EX
3030
if timeout > 0:
3131
lock_flags |= fcntl.LOCK_NB
32-
end_time = time.time() + timeout if timeout > 0 else -1
32+
end_time = time.monotonic() + timeout if timeout > 0 else -1
3333
while True:
3434
try:
3535
fcntl.flock(lock_fd, lock_flags)
3636
break
3737
except IOError:
38-
if time.time() > end_time:
38+
if time.monotonic() > end_time:
3939
os.close(lock_fd)
4040
raise
4141
return lock_fd

aexpect/utils/wait.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ def wait_for(func, timeout, first=0.0, step=1.0, text=None):
3030
:param step: Time to sleep between attempts in seconds
3131
:param text: Text to print while waiting, for debug purposes
3232
"""
33-
start_time = time.time()
34-
end_time = time.time() + timeout
33+
start_time = time.monotonic()
34+
end_time = time.monotonic() + timeout
3535

3636
time.sleep(first)
3737

38-
while time.time() < end_time:
38+
while time.monotonic() < end_time:
3939
if text:
40-
_LOG.debug("%s (%f secs)", text, (time.time() - start_time))
40+
_LOG.debug("%s (%f secs)", text, (time.monotonic() - start_time))
4141

4242
output = func()
4343
if output:

0 commit comments

Comments
 (0)