summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrabhu Ramachandran2017-04-27 17:28:44 +0530
committerGitHub2017-04-27 17:28:44 +0530
commita67f8597da19527669b596fab08083a18c7e1fcc (patch)
tree26484d05a23223df13aabb42fe674ce759e09187
parentea9e60c47b763515b324aa507da06a1e91c488c6 (diff)
parent4a8f9a117f6a784fe722b8b381368c41be86024a (diff)
downloadonline_test-a67f8597da19527669b596fab08083a18c7e1fcc.tar.gz
online_test-a67f8597da19527669b596fab08083a18c7e1fcc.tar.bz2
online_test-a67f8597da19527669b596fab08083a18c7e1fcc.zip
Merge pull request #274 from maheshgudi/kill_stray_processes
Kill stray processes
-rw-r--r--requirements/requirements-common.txt1
-rw-r--r--yaksh/base_evaluator.py5
-rw-r--r--yaksh/bash_stdio_evaluator.py3
-rw-r--r--yaksh/cpp_stdio_evaluator.py3
-rw-r--r--yaksh/evaluator_tests/test_bash_evaluation.py10
-rw-r--r--yaksh/evaluator_tests/test_c_cpp_evaluation.py13
-rw-r--r--yaksh/evaluator_tests/test_java_evaluation.py16
-rw-r--r--yaksh/evaluator_tests/test_scilab_evaluation.py9
-rw-r--r--yaksh/hook_evaluator.py6
-rw-r--r--yaksh/java_stdio_evaluator.py3
-rw-r--r--yaksh/stdio_evaluator.py13
11 files changed, 72 insertions, 10 deletions
diff --git a/requirements/requirements-common.txt b/requirements/requirements-common.txt
index e04c5bd..53a44a4 100644
--- a/requirements/requirements-common.txt
+++ b/requirements/requirements-common.txt
@@ -5,3 +5,4 @@ python-social-auth==0.2.19
tornado
selenium==2.53.6
coverage
+psutil
diff --git a/yaksh/base_evaluator.py b/yaksh/base_evaluator.py
index 071008f..e702f68 100644
--- a/yaksh/base_evaluator.py
+++ b/yaksh/base_evaluator.py
@@ -7,6 +7,7 @@ from os.path import join, isfile
from os.path import isdir, dirname, abspath, join, isfile, exists
import subprocess
import stat
+import signal
# Local imports
@@ -30,11 +31,11 @@ class BaseEvaluator(object):
stdout and stderr.
"""
try:
- proc = subprocess.Popen(cmd_args, *args, **kw)
+ proc = subprocess.Popen(cmd_args,preexec_fn=os.setpgrp, *args, **kw)
stdout, stderr = proc.communicate()
except TimeoutException:
# Runaway code, so kill it.
- proc.kill()
+ os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
# Re-raise exception.
raise
return proc, stdout.decode('utf-8'), stderr.decode('utf-8')
diff --git a/yaksh/bash_stdio_evaluator.py b/yaksh/bash_stdio_evaluator.py
index 334620d..1ce729a 100644
--- a/yaksh/bash_stdio_evaluator.py
+++ b/yaksh/bash_stdio_evaluator.py
@@ -49,7 +49,8 @@ class BashStdIOEvaluator(StdIOEvaluator):
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
- stderr=subprocess.PIPE
+ stderr=subprocess.PIPE,
+ preexec_fn=os.setpgrp
)
success, err = self.evaluate_stdio(self.user_answer, proc,
self.expected_input,
diff --git a/yaksh/cpp_stdio_evaluator.py b/yaksh/cpp_stdio_evaluator.py
index b302fa4..d211bb7 100644
--- a/yaksh/cpp_stdio_evaluator.py
+++ b/yaksh/cpp_stdio_evaluator.py
@@ -82,7 +82,8 @@ class CppStdIOEvaluator(StdIOEvaluator):
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
- stderr=subprocess.PIPE
+ stderr=subprocess.PIPE,
+ preexec_fn=os.setpgrp
)
success, err = self.evaluate_stdio(self.user_answer, proc,
self.expected_input,
diff --git a/yaksh/evaluator_tests/test_bash_evaluation.py b/yaksh/evaluator_tests/test_bash_evaluation.py
index 482d45e..8bb8c81 100644
--- a/yaksh/evaluator_tests/test_bash_evaluation.py
+++ b/yaksh/evaluator_tests/test_bash_evaluation.py
@@ -3,6 +3,8 @@ import unittest
import os
import shutil
import tempfile
+from psutil import Process, pid_exists
+# Local Imports
from yaksh.grader import Grader
from yaksh.bash_code_evaluator import BashCodeEvaluator
from yaksh.bash_stdio_evaluator import BashStdIOEvaluator
@@ -103,6 +105,10 @@ class BashAssertionEvaluationTestCases(EvaluatorBaseTest):
# Then
self.assertFalse(result.get("success"))
self.assert_correct_output(self.timeout_msg, result.get("error"))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
def test_file_based_assert(self):
# Given
@@ -528,6 +534,10 @@ class BashHookEvaluationTestCases(EvaluatorBaseTest):
# Then
self.assertFalse(result.get('success'))
self.assert_correct_output(self.timeout_msg, result.get('error'))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
if __name__ == '__main__':
diff --git a/yaksh/evaluator_tests/test_c_cpp_evaluation.py b/yaksh/evaluator_tests/test_c_cpp_evaluation.py
index 304f1cb..b15f766 100644
--- a/yaksh/evaluator_tests/test_c_cpp_evaluation.py
+++ b/yaksh/evaluator_tests/test_c_cpp_evaluation.py
@@ -4,6 +4,7 @@ import os
import shutil
import tempfile
from textwrap import dedent
+from psutil import Process
# Local import
from yaksh.grader import Grader
@@ -151,6 +152,10 @@ class CAssertionEvaluationTestCases(EvaluatorBaseTest):
# Then
self.assertFalse(result.get("success"))
self.assert_correct_output(self.timeout_msg, result.get("error"))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
def test_file_based_assert(self):
# Given
@@ -401,6 +406,10 @@ class CppStdIOEvaluationTestCases(EvaluatorBaseTest):
# Then
self.assertFalse(result.get("success"))
self.assert_correct_output(self.timeout_msg, result.get("error"))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
def test_only_stdout(self):
# Given
@@ -967,6 +976,10 @@ class CppHookEvaluationTestCases(EvaluatorBaseTest):
# Then
self.assertFalse(result.get('success'))
self.assert_correct_output(self.timeout_msg, result.get('error'))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
if __name__ == '__main__':
diff --git a/yaksh/evaluator_tests/test_java_evaluation.py b/yaksh/evaluator_tests/test_java_evaluation.py
index 3d127af..ea558ed 100644
--- a/yaksh/evaluator_tests/test_java_evaluation.py
+++ b/yaksh/evaluator_tests/test_java_evaluation.py
@@ -4,6 +4,9 @@ import os
import shutil
import tempfile
from textwrap import dedent
+from psutil import Process, pid_exists
+import time
+
# Local Import
from yaksh import grader as gd
@@ -158,6 +161,10 @@ class JavaAssertionEvaluationTestCases(EvaluatorBaseTest):
# Then
self.assertFalse(result.get("success"))
self.assert_correct_output(self.timeout_msg, result.get("error"))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
def test_file_based_assert(self):
# Given
@@ -398,6 +405,10 @@ class JavaStdIOEvaluationTestCases(EvaluatorBaseTest):
# Then
self.assertFalse(result.get("success"))
self.assert_correct_output(self.timeout_msg, result.get("error"))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
def test_only_stdout(self):
# Given
@@ -832,8 +843,13 @@ class JavaHookEvaluationTestCases(EvaluatorBaseTest):
result = grader.evaluate(kwargs)
# Then
+
self.assertFalse(result.get('success'))
self.assert_correct_output(self.timeout_msg, result.get('error'))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
if __name__ == '__main__':
diff --git a/yaksh/evaluator_tests/test_scilab_evaluation.py b/yaksh/evaluator_tests/test_scilab_evaluation.py
index 5a452a3..c3a1c83 100644
--- a/yaksh/evaluator_tests/test_scilab_evaluation.py
+++ b/yaksh/evaluator_tests/test_scilab_evaluation.py
@@ -3,13 +3,15 @@ import unittest
import os
import shutil
import tempfile
+from psutil import Process
from textwrap import dedent
+
+#Local Import
from yaksh import grader as gd
from yaksh.grader import Grader
from yaksh.scilab_code_evaluator import ScilabCodeEvaluator
from yaksh.evaluator_tests.test_python_evaluation import EvaluatorBaseTest
-
class ScilabEvaluationTestCases(EvaluatorBaseTest):
def setUp(self):
tmp_in_dir_path = tempfile.mkdtemp()
@@ -136,6 +138,11 @@ class ScilabEvaluationTestCases(EvaluatorBaseTest):
self.assertFalse(result.get("success"))
self.assert_correct_output(self.timeout_msg, result.get("error"))
+ parent_proc = Process(os.getpid()).children()
+ if parent_proc:
+ children_procs = Process(parent_proc[0].pid)
+ self.assertFalse(any(children_procs.children(recursive=True)))
+
if __name__ == '__main__':
unittest.main()
diff --git a/yaksh/hook_evaluator.py b/yaksh/hook_evaluator.py
index 0819ec9..f5364d6 100644
--- a/yaksh/hook_evaluator.py
+++ b/yaksh/hook_evaluator.py
@@ -2,6 +2,8 @@
import sys
import traceback
import os
+import signal
+import psutil
# Local imports
from .file_utils import copy_files, delete_files
@@ -65,10 +67,12 @@ class HookEvaluator(BaseEvaluator):
check = hook_scope["check_answer"]
success, err, mark_fraction = check(self.user_answer)
except TimeoutException:
+ processes = psutil.Process(os.getpid()).children(recursive=True)
+ for process in processes:
+ process.kill()
raise
except Exception:
msg = traceback.format_exc(limit=0)
err = "Error in Hook code: {0}".format(msg)
del tb
return success, err, mark_fraction
- \ No newline at end of file
diff --git a/yaksh/java_stdio_evaluator.py b/yaksh/java_stdio_evaluator.py
index 48f265d..4e9238f 100644
--- a/yaksh/java_stdio_evaluator.py
+++ b/yaksh/java_stdio_evaluator.py
@@ -67,7 +67,8 @@ class JavaStdIOEvaluator(StdIOEvaluator):
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
- stderr=subprocess.PIPE
+ stderr=subprocess.PIPE,
+ preexec_fn=os.setpgrp
)
success, err = self.evaluate_stdio(self.user_answer, proc,
self.expected_input,
diff --git a/yaksh/stdio_evaluator.py b/yaksh/stdio_evaluator.py
index fa78a68..554d4c5 100644
--- a/yaksh/stdio_evaluator.py
+++ b/yaksh/stdio_evaluator.py
@@ -1,7 +1,10 @@
from __future__ import unicode_literals
+import os
+import signal
# Local imports
from .base_evaluator import BaseEvaluator
+from .grader import TimeoutException
class StdIOEvaluator(BaseEvaluator):
@@ -9,9 +12,13 @@ class StdIOEvaluator(BaseEvaluator):
success = False
ip = expected_input.replace(",", " ")
encoded_input = '{0}\n'.format(ip).encode('utf-8')
- user_output_bytes, output_err_bytes = proc.communicate(encoded_input)
- user_output = user_output_bytes.decode('utf-8')
- output_err = output_err_bytes.decode('utf-8')
+ try:
+ user_output_bytes, output_err_bytes = proc.communicate(encoded_input)
+ user_output = user_output_bytes.decode('utf-8')
+ output_err = output_err_bytes.decode('utf-8')
+ except TimeoutException:
+ os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
+ raise
expected_output = expected_output.replace("\r", "")
if not expected_input:
error_msg = "Expected Output is\n{0} ".\