def test_kill_task_terminate_with_sigkill(self): task_id = tu.get_random_task_id() stdout_name = tu.ensure_directory('build/stdout.{}'.format(task_id)) stderr_name = tu.ensure_directory('build/stderr.{}'.format(task_id)) tu.redirect_stdout_to_file(stdout_name) tu.redirect_stderr_to_file(stderr_name) try: command = "trap '' TERM SIGTERM; sleep 200" process = cs.launch_process(command, {}) shutdown_grace_period_ms = 1000 group_id = cs.find_process_group(process.pid) self.assertGreater(len(find_process_ids_in_group(group_id)), 0) cs.kill_process(process, shutdown_grace_period_ms) # await process termination for i in range(1, 10 * shutdown_grace_period_ms): if process.poll() is None: time.sleep(0.01) if process.poll() is None: process.kill() self.assertTrue( ((-1 * signal.SIGKILL) == process.poll()) or ((128 + signal.SIGKILL) == process.poll()), 'Process exited with code {}'.format(process.poll())) self.assertEqual(len(find_process_ids_in_group(group_id)), 0) finally: tu.cleanup_output(stdout_name, stderr_name)
def test_kill_task_terminate_with_sigterm(self): task_id = tu.get_random_task_id() stdout_name = tu.ensure_directory('build/stdout.{}'.format(task_id)) stderr_name = tu.ensure_directory('build/stderr.{}'.format(task_id)) tu.redirect_stdout_to_file(stdout_name) tu.redirect_stderr_to_file(stderr_name) try: command = "bash -c 'function handle_term { echo GOT TERM; }; trap handle_term SIGTERM TERM; sleep 200'" process = cs.launch_process(command, {}) shutdown_grace_period_ms = 1000 group_id = cs.find_process_group(process.pid) self.assertGreater(len(find_process_ids_in_group(group_id)), 0) cs.kill_process(process, shutdown_grace_period_ms) # await process termination for i in range(1, 10 * shutdown_grace_period_ms): if process.poll() is None: time.sleep(0.01) if process.poll() is None: process.kill() self.assertTrue( ((-1 * signal.SIGTERM) == process.poll()) or ((128 + signal.SIGTERM) == process.poll()), 'Process exited with code {}'.format(process.poll())) self.assertEqual(0, len(find_process_ids_in_group(group_id))) with open(stdout_name) as f: file_contents = f.read() self.assertTrue('GOT TERM' in file_contents) finally: tu.cleanup_output(stdout_name, stderr_name)
def process_launch_and_kill_helper(self, kill_fn): task_id = tu.get_random_task_id() stdout_name = tu.ensure_directory('build/stdout.{}'.format(task_id)) stderr_name = tu.ensure_directory('build/stderr.{}'.format(task_id)) tu.redirect_stdout_to_file(stdout_name) tu.redirect_stderr_to_file(stderr_name) try: start_time = time.time() command = 'echo "A.$(sleep 30)" & echo "B.$(sleep 30)" & echo "C.$(sleep 30)" &' environment = {} process = cs.launch_process(command, environment) group_id = cs.find_process_group(process.pid) self.assertGreater(group_id, 0) child_process_ids = tu.wait_for( lambda: find_process_ids_in_group(group_id), lambda data: len(data) >= 7, default_value=[]) self.assertGreaterEqual(len(child_process_ids), 7) self.assertLessEqual(len(child_process_ids), 10) kill_fn(process.pid) child_process_ids = tu.wait_for( lambda: find_process_ids_in_group(group_id), lambda data: len(data) == 0, default_value=[]) self.assertEqual(0, len(child_process_ids)) # ensure the test ran in under 30 seconds self.assertLess(time.time() - start_time, 20) finally: tu.cleanup_output(stdout_name, stderr_name)
def launch_task(task, environment): """Launches the task using the command available in the json map from the data field. Parameters ---------- task: dictionary The task to execute. environment: dictionary The task environment. Returns ------- When command is provided and a process can be started, the process launched. Else it logs the reason and returns None. """ try: data_string = pm.decode_data(task['data']).decode('utf8') data_json = json.loads(data_string) command = str(data_json['command']).strip() logging.info('Command: {}'.format(command)) return cs.launch_process(command, environment) except Exception: logging.exception('Error in launch_task') return None