summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJames Cammarata <jimi@sngx.net>2014-04-08 20:21:42 +0200
committerJames Cammarata <jimi@sngx.net>2014-04-08 20:21:42 +0200
commiteebc72ab9b1cf61ab3bdbe61b92636c0bae22873 (patch)
tree393181b78b01e48ad20128e83a288652f329672b /lib
parentFix incorrect version_added value in docstring for subversion export param (diff)
downloadansible-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.py47
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')