Ejemplo n.º 1
0
 def test_timeout_expired__repr__(self):
     self.assertEqual(
         repr(psutil.TimeoutExpired(5)),
         "psutil.TimeoutExpired(seconds=5, msg='timeout after 5 seconds')")
     self.assertEqual(
         repr(psutil.TimeoutExpired(5, pid=321, name="name")),
         "psutil.TimeoutExpired(pid=321, name='name', seconds=5, "
         "msg='timeout after 5 seconds')")
Ejemplo n.º 2
0
 def test_timeout_expired__repr__(self, func=repr):
     self.assertEqual(repr(psutil.TimeoutExpired(321)),
                      "psutil.TimeoutExpired timeout after 321 seconds")
     self.assertEqual(
         repr(psutil.TimeoutExpired(321, pid=111)),
         "psutil.TimeoutExpired timeout after 321 seconds (pid=111)")
     self.assertEqual(
         repr(psutil.TimeoutExpired(321, pid=111, name='foo')),
         "psutil.TimeoutExpired timeout after 321 seconds "
         "(pid=111, name='foo')")
Ejemplo n.º 3
0
    def test_stop(self, mock_is_running):
        # Postmaster is not running
        mock_callback = Mock()
        mock_is_running.return_value = None
        self.assertTrue(self.p.stop(on_safepoint=mock_callback))
        mock_callback.assert_called()

        # Is running, stopped successfully
        mock_is_running.return_value = mock_postmaster = MockPostmaster()
        mock_callback.reset_mock()
        self.assertTrue(self.p.stop(on_safepoint=mock_callback))
        mock_callback.assert_called()
        mock_postmaster.signal_stop.assert_called()

        # Timed out waiting for fast shutdown triggers immediate shutdown
        mock_postmaster.wait.side_effect = [
            psutil.TimeoutExpired(30),
            psutil.TimeoutExpired(30),
            Mock()
        ]
        mock_callback.reset_mock()
        self.assertTrue(
            self.p.stop(on_safepoint=mock_callback, stop_timeout=30))
        mock_callback.assert_called()
        mock_postmaster.signal_stop.assert_called()

        # Immediate shutdown succeeded
        mock_postmaster.wait.side_effect = [psutil.TimeoutExpired(30), Mock()]
        self.assertTrue(
            self.p.stop(on_safepoint=mock_callback, stop_timeout=30))

        # Stop signal failed
        mock_postmaster.signal_stop.return_value = False
        self.assertFalse(self.p.stop())

        # Stop signal failed to find process
        mock_postmaster.signal_stop.return_value = True
        mock_callback.reset_mock()
        self.assertTrue(self.p.stop(on_safepoint=mock_callback))
        mock_callback.assert_called()

        # Fast shutdown is timed out but when immediate postmaster is already gone
        mock_postmaster.wait.side_effect = [psutil.TimeoutExpired(30), Mock()]
        mock_postmaster.signal_stop.side_effect = [None, True]
        self.assertTrue(
            self.p.stop(on_safepoint=mock_callback, stop_timeout=30))
Ejemplo n.º 4
0
 def wait(self, timeout):
     print("running", self.running)
     print("timed out", timeout, self.terminate_time)
     if not self.running or self.terminate_time < timeout:
         return
     raise psutil.TimeoutExpired(
         "time to terminate {} exceeds timeout {}".format(
             self.terminate, timeout))
Ejemplo n.º 5
0
def make_mock_process(
    pid,  # type: int
    open_files=None,  # type: Optional[List]
    name="",  # type: str
    cmdline="",  # type: str
    create_time=0.0,  # type: float
    as_dict_throw=False,  # type: bool
    signal_throw=False,  # type: bool
    wait_throw=False,  # type: bool
    cmdline_throw=False,  # type: bool
    timeout=False,  # type: bool
):
    # type: (...) -> psutil.Process
    """
    Creates a mock psutil.Process object suitable for these unit tests. If
    `throw` is True, it sets the side_effect of `as_dict` to throw a
    NoSuchProcess exception.
    """
    if open_files is None:
        open_files = []
    cmd = str(cmdline).split()
    if len(cmd) > 1 and name == "":
        name = cmd[0]
    mock_process = create_autospec(psutil.Process)
    mock_process.pid = pid
    mock_process.create_time.return_value = create_time
    mock_process.name.return_value = name
    mock_process.as_dict.__name__ = "as_dict"
    if as_dict_throw:
        mock_process.as_dict.side_effect = psutil.NoSuchProcess(pid)

    # This is hacky, but it works to simulate a TimeoutExpired actually being
    # raised by as_dict.
    elif timeout:
        mock_process.as_dict.side_effect = TimeoutExpired()
    else:
        mock_process.as_dict.return_value = {
            "pid": pid,
            "open_files": [MockPopenFile(f) for f in open_files],
        }
    if signal_throw:
        mock_process.send_signal.side_effect = psutil.NoSuchProcess(pid)
    else:
        mock_process.send_signal.return_value = None
    if wait_throw:
        mock_process.wait.side_effect = psutil.TimeoutExpired(5)
    else:
        mock_process.wait.return_value = None
    if cmdline_throw:
        mock_process.cmdline.side_effect = psutil.NoSuchProcess(pid)
    else:
        mock_process.cmdline.return_value = cmd

    return mock_process
Ejemplo n.º 6
0
    def wait(self, timeout=None):  # pylint: disable=unused-argument
        """Wait for the process completion.

        Mocks the process waiting for completion before it continues execution.
        No time is actually spent waiting, however, since the lifetime of the
        program is completely defined by the initialization params.

        Args:
            timeout: int|None. Time to wait before raising an exception, or None
                to wait indefinitely.
        """
        if not self.alive:
            return

        if not self.unresponsive:
            self._exit()
        elif timeout is not None:
            raise psutil.TimeoutExpired(timeout)
        else:
            raise RuntimeError('PopenStub has entered an infinite loop')
Ejemplo n.º 7
0
def make_mock_process(
    pid,
    open_files,
    name='',
    as_dict_throw=False,
    signal_throw=False,
    wait_throw=False,
    timeout=False,
):
    # type: (int, List[str], str, bool, bool, bool) -> psutil.Process
    """
    Creates a mock psutil.Process object suitable for these unit tests. If
    `throw` is True, it sets the side_effect of `as_dict` to throw a
    NoSuchProcess exception.
    """
    mock_process = create_autospec(psutil.Process)
    mock_process.pid = pid
    mock_process.name.return_value = name
    mock_process.as_dict.__name__ = 'as_dict'
    if as_dict_throw:
        mock_process.as_dict.side_effect = psutil.NoSuchProcess(pid)

    # This is hacky, but it works to simulate a TimeoutExpired actually being
    # raised by as_dict.
    elif timeout:
        mock_process.as_dict.side_effect = TimeoutExpired()
    else:
        mock_process.as_dict.return_value = {
            'pid': pid,
            'open_files': [MockPopenFile(f) for f in open_files],
        }
    if signal_throw:
        mock_process.send_signal.side_effect = psutil.NoSuchProcess(pid)
    else:
        mock_process.send_signal.return_value = None
    if wait_throw:
        mock_process.wait.side_effect = psutil.TimeoutExpired(5)
    else:
        mock_process.wait.return_value = None

    return mock_process
Ejemplo n.º 8
0
 def wait(self, timeout=None):
     raise psutil.TimeoutExpired(timeout)
Ejemplo n.º 9
0
def run_command(cmd,
                stdout=None,
                stderr=None,
                shell=False,
                timeout=None,
                cwd=None,
                env=None,
                universal_newlines=False):
  """Runs a command in a subprocess.

  This function is very similar to subprocess.check_output. The main
  difference is that it returns the return code and std error output as well
  as supporting a timeout parameter.

  Args:
    cmd: string or list of strings, the command to run.
      See subprocess.Popen() documentation.
    stdout: file handle, the file handle to write std out to. If None is
      given, then subprocess.PIPE is used. See subprocess.Popen()
      documentation.
    stderr: file handle, the file handle to write std err to. If None is
      given, then subprocess.PIPE is used. See subprocess.Popen()
      documentation.
    shell: bool, True to run this command through the system shell,
      False to invoke it directly. See subprocess.Popen() docs.
    timeout: float, the number of seconds to wait before timing out.
      If not specified, no timeout takes effect.
    cwd: string, the path to change the child's current directory to before
      it is executed. Note that this directory is not considered when
      searching the executable, so you can't specify the program's path
      relative to cwd.
    env: dict, a mapping that defines the environment variables for the
      new process. Default behavior is inheriting the current process'
      environment.
    universal_newlines: bool, True to open file objects in text mode, False in
      binary mode.

  Returns:
    A 3-tuple of the consisting of the return code, the std output, and the
      std error.

  Raises:
    psutil.TimeoutExpired: The command timed out.
  """
  # Only import psutil when actually needed.
  # psutil may cause import error in certain env. This way the utils module
  # doesn't crash upon import.
  import psutil
  if stdout is None:
    stdout = subprocess.PIPE
  if stderr is None:
    stderr = subprocess.PIPE
  process = psutil.Popen(cmd,
                         stdout=stdout,
                         stderr=stderr,
                         shell=shell,
                         cwd=cwd,
                         env=env,
                         universal_newlines=universal_newlines)
  timer = None
  timer_triggered = threading.Event()
  if timeout and timeout > 0:
    # The wait method on process will hang when used with PIPEs with large
    # outputs, so use a timer thread instead.

    def timeout_expired():
      timer_triggered.set()
      process.terminate()

    timer = threading.Timer(timeout, timeout_expired)
    timer.start()
  # If the command takes longer than the timeout, then the timer thread
  # will kill the subprocess, which will make it terminate.
  (out, err) = process.communicate()
  if timer is not None:
    timer.cancel()
  if timer_triggered.is_set():
    raise psutil.TimeoutExpired(timeout, pid=process.pid)
  return (process.returncode, out, err)
Ejemplo n.º 10
0
 def test_timeout_expired__str__(self):
     self.assertEqual(str(psutil.TimeoutExpired(5)),
                      "timeout after 5 seconds")
     self.assertEqual(str(psutil.TimeoutExpired(5, pid=321, name="name")),
                      "timeout after 5 seconds (pid=321, name='name')")
Ejemplo n.º 11
0
def run_command(cmd,
                stdout=None,
                stderr=None,
                shell=False,
                timeout=None,
                env=None):
    """Runs a command in a subprocess.

    This function is very similar to subprocess.check_output. The main
    difference is that it returns the return code and std error output as well
    as supporting a timeout parameter.

    Args:
        cmd: string or list of strings, the command to run.
            See subprocess.Popen() documentation.
        stdout: file handle, the file handle to write std out to. If None is
            given, then subprocess.PIPE is used. See subprocess.Popen()
            documentation.
        stdee: file handle, the file handle to write std err to. If None is
            given, then subprocess.PIPE is used. See subprocess.Popen()
            documentation.
        shell: bool, True to run this command through the system shell,
            False to invoke it directly. See subprocess.Popen() docs.
        timeout: float, the number of seconds to wait before timing out.
            If not specified, no timeout takes effect.

    Returns:
        A 3-tuple of the consisting of the return code, the std output, and the
            std error.

    Raises:
        psutil.TimeoutExpired: The command timed out.
    """
    # Only import psutil when actually needed.
    # psutil may cause import error in certain env. This way the utils module
    # doesn't crash upon import.
    import psutil
    if stdout is None:
        stdout = subprocess.PIPE
    if stderr is None:
        stderr = subprocess.PIPE
    process = psutil.Popen(cmd,
                           stdout=stdout,
                           stderr=stderr,
                           shell=shell,
                           env=env)
    timer = None
    timer_triggered = threading.Event()
    if timeout and timeout > 0:
        # The wait method on process will hang when used with PIPEs with large
        # outputs, so use a timer thread instead.

        def timeout_expired():
            timer_triggered.set()
            process.terminate()

        timer = threading.Timer(timeout, timeout_expired)
        timer.start()
    # If the command takes longer than the timeout, then the timer thread
    # will kill the subprocess, which will make it terminate.
    (out, err) = process.communicate()
    if timer is not None:
        timer.cancel()
    if timer_triggered.is_set():
        raise psutil.TimeoutExpired(timeout, pid=process.pid)
    return (process.returncode, out, err)
def wait_for_process(pid, timeout=None):
    start_time = time.time()
    while True == is_process_active(pid):
        if timeout is not None and (time.time() - start_time) >= timeout:
            raise psutil.TimeoutExpired("Process is still alive")
        time.sleep(0.1)