예제 #1
0
 def get_real_python():
     """
     The reason why the virtualenv creation is proxied by this function is mostly
     because under windows, we can't seem to properly create a virtualenv off of
     another virtualenv(we can on Linux) and also because, we really don't want to
     test virtualenv creation off of another virtualenv, we want a virtualenv created
     from the original python.
     Also, on windows, we must also point to the virtualenv binary outside the existing
     virtualenv because it will fail otherwise
     """
     try:
         if platform.is_windows():
             return os.path.join(sys.real_prefix,
                                 os.path.basename(sys.executable))
         else:
             python_binary_names = [
                 "python{}.{}".format(*sys.version_info),
                 "python{}".format(*sys.version_info),
                 "python",
             ]
             for binary_name in python_binary_names:
                 python = os.path.join(sys.real_prefix, "bin", binary_name)
                 if os.path.exists(python):
                     break
             else:
                 raise AssertionError(
                     "Couldn't find a python binary name under '{}' matching: {}"
                     .format(os.path.join(sys.real_prefix, "bin"),
                             python_binary_names))
             return python
     except AttributeError:
         return sys.executable
예제 #2
0
 def get_base_script_args(self):
     """
     Return the base arguments for the daemon.
     """
     script_args = super().get_base_script_args()
     if platform.is_windows() is False:
         script_args.append("--disable-keepalive")
     return script_args
예제 #3
0
 def get_script_args(self):
     """
     Return the script arguments.
     """
     args = super().get_script_args()
     if platform.is_windows() is False:
         args.append("--disable-keepalive")
     return args
예제 #4
0
def test_daemon_process_termination(request, tempfiles):
    primary_childrend_count = 5
    secondary_children_count = 3
    script = tempfiles.makepyfile(
        """
        #!{shebang}
        # coding=utf-8

        import time
        import multiprocessing

        def spin():
            while True:
                try:
                    time.sleep(0.25)
                except KeyboardInterrupt:
                    break

        def spin_children():
            procs = []
            for idx in range({secondary_children_count}):
                proc = multiprocessing.Process(target=spin)
                proc.daemon = True
                proc.start()
                procs.append(proc)

            while True:
                try:
                    time.sleep(0.25)
                except KeyboardInterrupt:
                    break


        def main():
            procs = []

            for idx in range({primary_childrend_count}):
                proc = multiprocessing.Process(target=spin_children)
                procs.append(proc)
                proc.start()

            while True:
                try:
                    time.sleep(0.25)
                except KeyboardInterrupt:
                    break

            # We're not terminating child processes on purpose. Our code should handle it.

        # Support for windows test runs
        if __name__ == '__main__':
            multiprocessing.freeze_support()
            main()
        """.format(
            shebang=sys.executable,
            primary_childrend_count=primary_childrend_count,
            secondary_children_count=secondary_children_count,
        ),
        executable=True,
    )
    if not platform.is_windows():
        factory_kwargs = dict(script_name=script)
    else:
        # Windows don't know how to handle python scripts directly
        factory_kwargs = dict(script_name=sys.executable, base_script_args=[script])
    daemon = Daemon(start_timeout=1, **factory_kwargs)
    daemon.start()
    daemon_pid = daemon.pid
    # Make sure the daemon is terminated no matter what
    request.addfinalizer(daemon.terminate)
    # Allow the script to start
    time.sleep(PROCESS_START_TIMEOUT)
    assert psutil.pid_exists(daemon_pid)
    proc = psutil.Process(daemon_pid)
    children = proc.children(recursive=True)
    request.addfinalizer(functools.partial(kill_children, children))
    child_count = len(children)
    expected_count = primary_childrend_count + (primary_childrend_count * secondary_children_count)
    if platform.is_windows() and sys.version_info[:2] == (3, 7):
        # Under Python 3.7 and Windows we always seem to get +1 child
        # XXX: Don't forget to look what this extra child is
        expected_count += 1
    assert child_count == expected_count, "{}!={}\n{}".format(
        child_count,
        expected_count,
        pprint.pformat([_get_cmdline(child) or child for child in children]),
    )
    daemon.terminate()
    assert psutil.pid_exists(daemon_pid) is False
    for child in list(children):  # pragma: no cover
        if psutil.pid_exists(child.pid):
            continue
        children.remove(child)
    assert not children, "len(children)=={} != 0\n{}".format(
        len(children), pprint.pformat([_get_cmdline(child) or child for child in children])
    )
예제 #5
0
def test_daemon_process_termination_parent_killed(request, tempfiles):

    primary_childrend_count = 5
    secondary_children_count = 3
    script = tempfiles.makepyfile(
        """
        #!{shebang}
        # coding=utf-8

        import time
        import multiprocessing

        def spin():
            while True:
                try:
                    time.sleep(0.25)
                except KeyboardInterrupt:
                    break

        def spin_children():
            procs = []
            for idx in range({secondary_children_count}):
                proc = multiprocessing.Process(target=spin)
                proc.daemon = True
                proc.start()
                procs.append(proc)

            while True:
                try:
                    time.sleep(0.25)
                except KeyboardInterrupt:
                    break

        def main():
            procs = []

            for idx in range({primary_childrend_count}):
                proc = multiprocessing.Process(target=spin_children)
                procs.append(proc)
                proc.start()

            while True:
                try:
                    time.sleep(0.25)
                except KeyboardInterrupt:
                    break

            # We're not terminating child processes on purpose. Our code should handle it.

        # Support for windows test runs
        if __name__ == '__main__':
            multiprocessing.freeze_support()
            main()
        """.format(
            shebang=sys.executable,
            primary_childrend_count=primary_childrend_count,
            secondary_children_count=secondary_children_count,
        ),
        executable=True,
    )
    if not platform.is_windows():
        factory_kwargs = dict(script_name=script)
    else:
        # Windows don't know how to handle python scripts directly
        factory_kwargs = dict(script_name=sys.executable, base_script_args=[script])
    daemon = Daemon(start_timeout=1, **factory_kwargs)
    daemon.start()
    daemon_pid = daemon.pid
    # Make sure the daemon is terminated no matter what
    request.addfinalizer(daemon.terminate)
    # Allow the script to start
    time.sleep(PROCESS_START_TIMEOUT)
    assert psutil.pid_exists(daemon_pid)
    proc = psutil.Process(daemon_pid)
    children = proc.children(recursive=True)
    request.addfinalizer(functools.partial(kill_children, children))
    assert len(children) == primary_childrend_count + (
        primary_childrend_count * secondary_children_count
    )
    # Pretend the parent process died.
    proc.kill()
    time.sleep(0.5)
    # We should should still be able to terminate all child processes
    daemon.terminate()
    assert psutil.pid_exists(daemon_pid) is False
    psutil.wait_procs(children, timeout=3)
    for child in list(children):
        if psutil.pid_exists(child.pid):
            continue
        children.remove(child)
    assert not children, "len(children)=={} != 0\n{}".format(
        len(children), pprint.pformat(children)
    )
예제 #6
0
 def _default_log_host(self):
     if platform.is_windows():
         # Windows cannot bind to 0.0.0.0
         return "127.0.0.1"
     return "0.0.0.0"
예제 #7
0
 def _default_venv_python(self):
     # Once we drop Py3.5 we can stop casting to string
     if platform.is_windows():
         return str(self.venv_dir / "Scripts" / "python.exe")
     return str(self.venv_dir / "bin" / "python")
예제 #8
0
 def get_base_script_args(self):
     script_args = super().get_base_script_args()
     if platform.is_windows() is False:
         script_args.append("--disable-keepalive")
     return script_args