Chromium Code Reviews| Index: scripts/slave/recipe_modules/goma/resources/cloudtail_utils.py |
| diff --git a/scripts/slave/recipe_modules/goma/resources/cloudtail_utils.py b/scripts/slave/recipe_modules/goma/resources/cloudtail_utils.py |
| index bfe97d81c9b55bf1b895a97ad565957f9d21e63d..aafca9b8fe055d10b66c0cd691bbb3d858006fe8 100644 |
| --- a/scripts/slave/recipe_modules/goma/resources/cloudtail_utils.py |
| +++ b/scripts/slave/recipe_modules/goma/resources/cloudtail_utils.py |
| @@ -5,6 +5,7 @@ |
| import argparse |
| import errno |
| +import multiprocessing |
| import os |
| import signal |
| import subprocess |
| @@ -54,44 +55,86 @@ class NotDiedError(Exception): |
| return "NotDiedError" |
| -def wait_termination(pid): |
| - """Send SIGINT to pid and wait termination of pid. |
| +def wait_termination_win(pid): |
| + """Send CTRL_C_EVENT or SIGINT to pid and wait termination of pid. |
| Args: |
| pid(int): pid of process which this function waits termination. |
| - Raises: |
| - OSError: is_running_posix, os.waitpid and os.kill may throw OSError. |
| - NotDiedError: if cloudtail is running after 10 seconds waiting, |
| - NotDiedError is raised. |
| + Returns: |
| + None: if pid has already finished or process finished succesfully. |
| + instance of Exception: if raised unexpectedly. |
| """ |
| - |
| + import win32api |
| + import win32con |
| + import pywintypes |
| + handle = None |
| try: |
| - os.kill(pid, signal.SIGINT) |
| + handle = win32api.OpenProcess( |
| + win32con.PROCESS_QUERY_INFORMATION | win32con.SYNCHRONIZE, |
| + False, pid) |
| + try: |
| + os.kill(pid, signal.CTRL_C_EVENT) |
| + print('CTRL_C_EVENT has been sent to process %d. ' |
| + 'Going to wait for the process finishes.' % pid) |
| + except WindowsError as e: # pylint: disable=E0602 |
| + # If a target process does not share terminal, we cannot send Ctrl-C. |
| + if e.errno == 87: # 87 == invalid parameter |
| + os.kill(pid, signal.SIGINT) |
| + os.waitpid(handle, 0) |
|
Vadim Sh.
2016/10/25 18:35:41
I think it would be simpler to use WaitForSingleOb
Yoshisato Yanagisawa
2016/10/26 01:17:45
Done.
|
| + return None |
| + except pywintypes.error as e: |
| + if e[0] == 87 and e[1] == 'OpenProcess': |
| + print('Can\'t open process %d. Already dead? error %d.' % (pid, e)) |
| + return None |
| + raise |
| except OSError as e: |
| - # Already dead? |
| if e.errno in (errno.ECHILD, errno.EPERM, errno.ESRCH): |
| print('Can\'t send SIGINT to process %d. Already dead? Errno %d.' % |
| (pid, e.errno)) |
| - return |
| + return None |
| raise |
| + except Exception as e: |
| + return e |
|
Vadim Sh.
2016/10/25 18:35:41
this is weird... is it because of 'multiprocessing
Yoshisato Yanagisawa
2016/10/26 01:17:45
right. revised without multiprocessing.
|
| + finally: |
| + if handle: |
| + win32api.CloseHandle(handle) |
| + |
| + |
| +def wait_termination(pid): |
| + """Send SIGINT to pid and wait termination of pid. |
| - print('SIGINT has been sent to process %d. ' |
| - 'Going to wait for the process finishes.' % pid) |
| + Args: |
| + pid(int): pid of process which this function waits termination. |
| + |
| + Raises: |
| + OSError: is_running_posix, os.waitpid and os.kill may throw OSError. |
| + NotDiedError: if cloudtail is running after 10 seconds waiting, |
| + NotDiedError is raised. |
| + """ |
| if os.name == 'nt': |
| + pool = multiprocessing.Pool(1) |
| + res = pool.apply_async(wait_termination_win, [pid]) |
| try: |
| - os.waitpid(pid, 0) |
| + e = res.get(10) |
| + except multiprocessing.TimeoutError: |
| + print('process %d running more than 10 seconds.' % pid) |
| + raise NotDiedError() |
| + if e is None: |
| + return |
| + raise e |
| + else: |
| + try: |
| + os.kill(pid, signal.SIGINT) |
| except OSError as e: |
| - if e.errno == errno.ECHILD: |
| - print('process %d died before waitpitd' % pid) |
| + if e.errno in (errno.ECHILD, errno.EPERM, errno.ESRCH): |
| + print('Can\'t send SIGINT to process %d. Already dead? Errno %d.' % |
| + (pid, e.errno)) |
| return |
| - raise e |
| - else: |
| for _ in xrange(10): |
| time.sleep(1) |
| if not is_running_posix(pid): |
| return |
| - |
| print('process %d running more than 10 seconds' % pid) |
| raise NotDiedError() |
| @@ -127,7 +170,7 @@ def main(): |
| pid = int(f.read()) |
| try: |
| wait_termination(pid) |
| - except (OSError, NotDiedError) as e: |
| + except Exception as e: |
| print('Going to send SIGTERM to process %d due to Error %s' % (pid, e)) |
| # Since Windows does not have SIGKILL, we need to use SIGTERM. |
| try: |