From 1678c00d2b7cbe39b723b66c405803b6cc75196b Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Fri, 4 Jun 2021 15:23:33 +0200 Subject: [PATCH] Add `timeout()` class (#3460) * Add `timeout()` class * rearrange order --- utils/general.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/utils/general.py b/utils/general.py index 546fccd84066..591fc8474339 100755 --- a/utils/general.py +++ b/utils/general.py @@ -1,5 +1,6 @@ # YOLOv5 general utils +import contextlib import glob import logging import math @@ -7,6 +8,7 @@ import platform import random import re +import signal import subprocess import time import urllib @@ -34,6 +36,26 @@ os.environ['NUMEXPR_MAX_THREADS'] = str(min(os.cpu_count(), 8)) # NumExpr max threads +class timeout(contextlib.ContextDecorator): + # Usage: @timeout(seconds) decorator or 'with timeout(seconds):' context manager + def __init__(self, seconds, *, timeout_message="", suppress_timeout_errors=True): + self.seconds = int(seconds) + self.timeout_message = timeout_message + self.suppress = bool(suppress_timeout_errors) + + def _timeout_handler(self, signum, frame): + raise TimeoutError(self.timeout_message) + + def __enter__(self): + signal.signal(signal.SIGALRM, self._timeout_handler) # Set handler for SIGALRM + signal.alarm(self.seconds) # start countdown for SIGALRM to be raised + + def __exit__(self, exc_type, exc_val, exc_tb): + signal.alarm(0) # Cancel SIGALRM if it's scheduled + if self.suppress and exc_type is TimeoutError: # Suppress TimeoutError + return True + + def set_logging(rank=-1, verbose=True): logging.basicConfig( format="%(message)s", @@ -86,7 +108,7 @@ def check_online(): # Check internet connectivity import socket try: - socket.create_connection(("1.1.1.1", 443), 5) # check host accesability + socket.create_connection(("1.1.1.1", 443), 5) # check host accessibility return True except OSError: return False