Skip to content

Commit

Permalink
Add timeout for each check
Browse files Browse the repository at this point in the history
Signed-off-by: lachmanfrantisek <[email protected]>
  • Loading branch information
lachmanfrantisek committed Nov 6, 2018
1 parent d440dee commit 7f1c157
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
9 changes: 8 additions & 1 deletion colin/core/check_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import logging
import traceback

from .constant import CHECK_TIMEOUT
from .result import CheckResults, FailedCheckResult
from ..utils.cmd_tools import exit_after

logger = logging.getLogger(__name__)

Expand All @@ -34,7 +36,12 @@ def _result_generator(target, checks):
for check in checks:
logger.debug("Checking {}".format(check.name))
try:
yield check.check(target)
timeout = check.timeout or CHECK_TIMEOUT
yield exit_after(timeout)(check.check)(target)
except TimeoutError as ex:
logger.warning(
"The check hit the timeout.")
yield FailedCheckResult(check, logs=[str(ex)])
except Exception as ex:
tb = traceback.format_exc()
logger.warning(
Expand Down
1 change: 1 addition & 0 deletions colin/core/checks/abstract_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(self, message, description, reference_url, tags):
self.description = description
self.reference_url = reference_url
self.tags = tags
self.timeout = None

def check(self, target):
pass
Expand Down
2 changes: 2 additions & 0 deletions colin/core/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@
}

COLIN_CHECKS_PATH = "CHECKS_PATH"

CHECK_TIMEOUT = 10 * 60 # s
37 changes: 36 additions & 1 deletion colin/utils/cmd_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import logging
import subprocess
import threading

try:
import thread
except ImportError:
import _thread as thread

logger = logging.getLogger(__name__)


def get_version_of_the_python_package(module):
Expand Down Expand Up @@ -85,3 +93,30 @@ def is_rpm_installed():
except FileNotFoundError:
rpm_installed = False
return rpm_installed


def exit_after(s):
"""
Use as decorator to exit process if
function takes longer than s seconds.
Direct call is available via exit_after(TIMEOUT_IN_S)(fce)(args).
Inspired by https://stackoverflow.com/a/31667005
"""

def outer(fn):
def inner(*args, **kwargs):
timer = threading.Timer(s, thread.interrupt_main)
timer.start()
try:
result = fn(*args, **kwargs)
except KeyboardInterrupt:
raise TimeoutError("Function '{}' hit the timeout ({}s).".format(fn.__name__, s))
finally:
timer.cancel()
return result

return inner

return outer

0 comments on commit 7f1c157

Please sign in to comment.