Commit 9da63815 authored by Pere Cortes's avatar Pere Cortes

Security Thread added to kill blocked process

parent 6acf7f5f
This diff is collapsed.
...@@ -30,6 +30,9 @@ import subprocess ...@@ -30,6 +30,9 @@ import subprocess
import threading import threading
import signal import signal
import sys import sys
import time
MAX_TIMEOUT = 5
class SubprocessError(EnvironmentError): class SubprocessError(EnvironmentError):
def __init__(self, status_dict): def __init__(self, status_dict):
...@@ -39,6 +42,12 @@ class SubprocessError(EnvironmentError): ...@@ -39,6 +42,12 @@ class SubprocessError(EnvironmentError):
def __str__(self): def __str__(self):
return 'Error %i' % self.status_code return 'Error %i' % self.status_code
class TimeoutError(EnvironmentError):
def __init__(self):
pass
def __str__(self):
return 'Timeout expired. Process killed'
class CancellationError(EnvironmentError): class CancellationError(EnvironmentError):
pass pass
...@@ -98,8 +107,16 @@ class ProcessManager(object): ...@@ -98,8 +107,16 @@ class ProcessManager(object):
self.process_pid_set = set() self.process_pid_set = set()
signal.signal(signal.SIGTERM, self.sigterm_handler) signal.signal(signal.SIGTERM, self.sigterm_handler)
self.under_cancellation = False self.under_cancellation = False
self.p = None
self.result = None
def spawn(self, *args, **kw): def spawn(self, *args, **kw):
def timeoutExpired(p):
time.sleep(MAX_TIMEOUT)
if p.poll() is None:
p.terminate()
raise TimeoutError
if self.under_cancellation: if self.under_cancellation:
raise CancellationError("Test Result was cancelled") raise CancellationError("Test Result was cancelled")
get_output = kw.pop('get_output', True) get_output = kw.pop('get_output', True)
...@@ -120,6 +137,8 @@ class ProcessManager(object): ...@@ -120,6 +137,8 @@ class ProcessManager(object):
p = subprocess.Popen(args, stdin=self.stdin, stdout=subprocess.PIPE, p = subprocess.Popen(args, stdin=self.stdin, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, env=env, **subprocess_kw) stderr=subprocess.PIPE, env=env, **subprocess_kw)
self.process_pid_set.add(p.pid) self.process_pid_set.add(p.pid)
thread = threading.Thread(target=timeoutExpired, args=(p,))
thread.start()
stdout, stderr = subprocess_capture(p, self.log, log_prefix, stdout, stderr = subprocess_capture(p, self.log, log_prefix,
get_output=get_output) get_output=get_output)
result = dict(status_code=p.returncode, command=command, result = dict(status_code=p.returncode, command=command,
...@@ -127,7 +146,7 @@ class ProcessManager(object): ...@@ -127,7 +146,7 @@ class ProcessManager(object):
self.process_pid_set.discard(p.pid) self.process_pid_set.discard(p.pid)
if self.under_cancellation: if self.under_cancellation:
raise CancellationError("Test Result was cancelled") raise CancellationError("Test Result was cancelled")
if raise_error_if_fail and p.returncode: if raise_error_if_fail and p.returncode != -15 and p.returncode:
raise SubprocessError(result) raise SubprocessError(result)
return result return result
......
...@@ -257,7 +257,7 @@ branch = %(branch)s ...@@ -257,7 +257,7 @@ branch = %(branch)s
We will build slapos software needed by the testnode itself, We will build slapos software needed by the testnode itself,
like the building of selenium-runner by default like the building of selenium-runner by default
""" """
self._prepareSlapOS(self.config['slapos_directory'], return self._prepareSlapOS(self.config['slapos_directory'],
test_node_slapos, create_partition=0, test_node_slapos, create_partition=0,
software_path_list=self.config.get("software_list")) software_path_list=self.config.get("software_list"))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment