diff options
author | James Cammarata <jimi@sngx.net> | 2014-04-08 20:21:42 +0200 |
---|---|---|
committer | James Cammarata <jimi@sngx.net> | 2014-04-08 20:21:42 +0200 |
commit | eebc72ab9b1cf61ab3bdbe61b92636c0bae22873 (patch) | |
tree | 393181b78b01e48ad20128e83a288652f329672b /lib | |
parent | Fix incorrect version_added value in docstring for subversion export param (diff) | |
download | ansible-eebc72ab9b1cf61ab3bdbe61b92636c0bae22873.tar.xz ansible-eebc72ab9b1cf61ab3bdbe61b92636c0bae22873.zip |
Add a timeout decorator for timing out functions that may hang
Fixes #6891
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ansible/module_utils/facts.py | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/lib/ansible/module_utils/facts.py b/lib/ansible/module_utils/facts.py index 607b911b0f..c056404210 100644 --- a/lib/ansible/module_utils/facts.py +++ b/lib/ansible/module_utils/facts.py @@ -17,11 +17,13 @@ import os import array +import errno import fcntl import fnmatch import glob import platform import re +import signal import socket import struct import datetime @@ -40,6 +42,33 @@ try: except ImportError: import simplejson as json +# -------------------------------------------------------------- +# timeout function to make sure some fact gathering +# steps do not exceed a time limit + +class TimeoutError(Exception): + pass + +def timeout(seconds=10, error_message=os.strerror(errno.ETIME)): + def decorator(func): + def _handle_timeout(signum, frame): + raise TimeoutError(error_message) + + def wrapper(*args, **kwargs): + signal.signal(signal.SIGALRM, _handle_timeout) + signal.alarm(seconds) + try: + result = func(*args, **kwargs) + finally: + signal.alarm(0) + return result + + return wrapper + + return decorator + +# -------------------------------------------------------------- + class Facts(object): """ This class should only attempt to populate those facts that @@ -498,7 +527,10 @@ class LinuxHardware(Hardware): self.get_memory_facts() self.get_dmi_facts() self.get_device_facts() - self.get_mount_facts() + try: + self.get_mount_facts() + except TimeoutError: + pass return self.facts def get_memory_facts(self): @@ -622,6 +654,7 @@ class LinuxHardware(Hardware): else: self.facts[k] = 'NA' + @timeout(10) def get_mount_facts(self): self.facts['mounts'] = [] mtab = get_file_content('/etc/mtab', '') @@ -919,7 +952,10 @@ class FreeBSDHardware(Hardware): self.get_memory_facts() self.get_dmi_facts() self.get_device_facts() - self.get_mount_facts() + try: + self.get_mount_facts() + except TimeoutError: + pass return self.facts def get_cpu_facts(self): @@ -962,6 +998,7 @@ class FreeBSDHardware(Hardware): self.facts['swaptotal_mb'] = data[1] self.facts['swapfree_mb'] = data[3] + @timeout(10) def get_mount_facts(self): self.facts['mounts'] = [] fstab = get_file_content('/etc/fstab') @@ -1041,7 +1078,10 @@ class NetBSDHardware(Hardware): def populate(self): self.get_cpu_facts() self.get_memory_facts() - self.get_mount_facts() + try: + self.get_mount_facts() + except TimeoutError: + pass return self.facts def get_cpu_facts(self): @@ -1085,6 +1125,7 @@ class NetBSDHardware(Hardware): val = data[1].strip().split(' ')[0] self.facts["%s_mb" % key.lower()] = long(val) / 1024 + @timeout(10) def get_mount_facts(self): self.facts['mounts'] = [] fstab = get_file_content('/etc/fstab') |