示例#1
0
def test_subprocess(debug_session, pyfile):
    @pyfile
    def child():
        import sys
        import backchannel
        backchannel.write_json(sys.argv)

    @pyfile
    def parent():
        import os
        import subprocess
        import sys
        argv = [sys.executable]
        argv += [sys.argv[1], '--arg1', '--arg2', '--arg3']
        env = os.environ.copy()
        process = subprocess.Popen(argv,
                                   env=env,
                                   stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        process.wait()

    debug_session.multiprocess = True
    debug_session.program_args += [child]
    debug_session.prepare_to_run(filename=parent, backchannel=True)
    debug_session.start_debugging()

    root_start_request, = debug_session.all_occurrences_of(
        Request('launch') | Request('attach'))
    root_process, = debug_session.all_occurrences_of(Event('process'))
    root_pid = int(root_process.body['systemProcessId'])

    child_subprocess = debug_session.wait_for_next(Event('ptvsd_subprocess'))
    assert child_subprocess == Event(
        'ptvsd_subprocess', {
            'rootProcessId': root_pid,
            'parentProcessId': root_pid,
            'processId': ANY.int,
            'port': ANY.int,
            'rootStartRequest': {
                'seq': ANY.int,
                'type': 'request',
                'command': root_start_request.command,
                'arguments': root_start_request.arguments,
            }
        })
    child_port = child_subprocess.body['port']
    debug_session.proceed()

    child_session = DebugSession(method='attach_socket', ptvsd_port=child_port)
    child_session.ignore_unobserved = debug_session.ignore_unobserved
    child_session.connect()
    child_session.handshake()
    child_session.start_debugging()

    child_argv = debug_session.read_json()
    assert child_argv == [child, '--arg1', '--arg2', '--arg3']

    debug_session.wait_for_exit()
示例#2
0
def test_subprocess(debug_session, pyfile, start_method, run_as):
    @pyfile
    def child():
        import sys
        import backchannel
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        backchannel.write_json(sys.argv)

    @pyfile
    def parent():
        import os
        import subprocess
        import sys
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        argv = [sys.executable, sys.argv[1], '--arg1', '--arg2', '--arg3']
        env = os.environ.copy()
        process = subprocess.Popen(argv, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        process.wait()

    debug_session.program_args += [child]
    debug_session.initialize(multiprocess=True, target=(run_as, parent), start_method=start_method, use_backchannel=True)
    debug_session.start_debugging()

    root_start_request, = debug_session.all_occurrences_of(Request('launch') | Request('attach'))
    root_process, = debug_session.all_occurrences_of(Event('process'))
    root_pid = int(root_process.body['systemProcessId'])

    child_subprocess = debug_session.wait_for_next(Event('ptvsd_subprocess'))
    assert child_subprocess == Event('ptvsd_subprocess', {
        'rootProcessId': root_pid,
        'parentProcessId': root_pid,
        'processId': ANY.int,
        'port': ANY.int,
        'rootStartRequest': {
            'seq': ANY.int,
            'type': 'request',
            'command': root_start_request.command,
            'arguments': root_start_request.arguments,
        }
    })
    child_pid = child_subprocess.body['processId']
    child_port = child_subprocess.body['port']
    debug_session.proceed()

    child_session = DebugSession(start_method=START_METHOD_CMDLINE, ptvsd_port=child_port, pid=child_pid)
    child_session.ignore_unobserved = debug_session.ignore_unobserved
    child_session.connect()
    child_session.handshake()
    child_session.start_debugging()

    child_argv = debug_session.read_json()
    assert child_argv == [child, '--arg1', '--arg2', '--arg3']

    child_session.wait_for_exit()
    debug_session.wait_for_exit()
示例#3
0
def test_autokill(debug_session, pyfile, start_method, run_as):
    @pyfile
    def child():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        while True:
            pass

    @pyfile
    def parent():
        import backchannel
        import os
        import subprocess
        import sys
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        argv = [sys.executable, sys.argv[1]]
        env = os.environ.copy()
        subprocess.Popen(argv, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        backchannel.read_json()

    debug_session.program_args += [child]
    debug_session.initialize(multiprocess=True, target=(run_as, parent), start_method=start_method, use_backchannel=True)
    debug_session.start_debugging()

    child_subprocess = debug_session.wait_for_next(Event('ptvsd_subprocess'))
    child_pid = child_subprocess.body['processId']
    child_port = child_subprocess.body['port']

    debug_session.proceed()

    child_session = DebugSession(start_method=START_METHOD_CMDLINE, ptvsd_port=child_port, pid=child_pid)
    child_session.expected_returncode = ANY
    child_session.connect()
    child_session.handshake()
    child_session.start_debugging()

    if debug_session.start_method == START_METHOD_LAUNCH:
        # In launch scenario, terminate the parent process by disconnecting from it.
        debug_session.expected_returncode = ANY
        disconnect = debug_session.send_request('disconnect', {})
        debug_session.wait_for_next(Response(disconnect))
    else:
        # In attach scenario, just let the parent process run to completion.
        debug_session.expected_returncode = 0
        debug_session.write_json(None)

    debug_session.wait_for_exit()
    child_session.wait_for_exit()
示例#4
0
def test_multiprocessing(debug_session, pyfile):
    @pyfile
    def code_to_debug():
        import multiprocessing
        import platform
        import sys

        def child_of_child(q):
            print('entering child of child')
            assert q.get() == 2
            q.put(3)
            print('leaving child of child')

        def child(q):
            print('entering child')
            assert q.get() == 1

            print('spawning child of child')
            p = multiprocessing.Process(target=child_of_child, args=(q, ))
            p.start()
            p.join()

            assert q.get() == 3
            q.put(4)
            print('leaving child')

        if __name__ == '__main__':
            import backchannel
            if sys.version_info >= (3, 4):
                multiprocessing.set_start_method('spawn')
            else:
                assert platform.system() == 'Windows'

            print('spawning child')
            q = multiprocessing.Queue()
            p = multiprocessing.Process(target=child, args=(q, ))
            p.start()
            print('child spawned')
            backchannel.write_json(p.pid)

            q.put(1)
            assert backchannel.read_json() == 'continue'
            q.put(2)
            p.join()
            assert q.get() == 4
            q.close()
            backchannel.write_json('done')

    debug_session.ignore_unobserved += [
        # The queue module can spawn helper background threads, depending on Python version
        # and platform. Since this is an implementation detail, we don't care about those.
        Event('thread', ANY.dict_with({'reason': 'started'}))
    ]

    debug_session.multiprocess = True
    debug_session.prepare_to_run(filename=code_to_debug, backchannel=True)
    debug_session.start_debugging()

    root_start_request, = debug_session.all_occurrences_of(
        Request('launch') | Request('attach'))
    root_process, = debug_session.all_occurrences_of(Event('process'))
    root_pid = int(root_process.body['systemProcessId'])

    child_pid = debug_session.read_json()

    child_subprocess = debug_session.wait_for_next(Event('ptvsd_subprocess'))
    assert child_subprocess == Event(
        'ptvsd_subprocess', {
            'rootProcessId': root_pid,
            'parentProcessId': root_pid,
            'processId': child_pid,
            'port': ANY.int,
            'rootStartRequest': {
                'seq': ANY.int,
                'type': 'request',
                'command': root_start_request.command,
                'arguments': root_start_request.arguments,
            }
        })
    child_port = child_subprocess.body['port']

    child_session = DebugSession(method='attach_socket', ptvsd_port=child_port)
    child_session.ignore_unobserved = debug_session.ignore_unobserved
    child_session.connect()
    child_session.handshake()
    child_session.start_debugging()

    debug_session.proceed()
    child_child_subprocess = debug_session.wait_for_next(
        Event('ptvsd_subprocess'))
    assert child_child_subprocess == Event(
        'ptvsd_subprocess', {
            'rootProcessId': root_pid,
            'parentProcessId': child_pid,
            'processId': ANY.int,
            'port': ANY.int,
            'rootStartRequest': {
                'seq': ANY.int,
                'type': 'request',
                'command': root_start_request.command,
                'arguments': root_start_request.arguments,
            }
        })
    child_child_port = child_child_subprocess.body['port']

    child_child_session = DebugSession(method='attach_socket',
                                       ptvsd_port=child_child_port)
    child_child_session.ignore_unobserved = debug_session.ignore_unobserved
    child_child_session.connect()
    child_child_session.handshake()
    child_child_session.start_debugging(freeze=False)

    debug_session.write_json('continue')

    if sys.version_info >= (3, ):
        child_child_session.wait_for_termination()
        child_session.wait_for_termination()
    else:
        # These should really be wait_for_termination(), but child processes don't send the
        # usual sequence of events leading to 'terminate' when they exit for some unclear
        # reason (ptvsd bug?). So, just wait till they drop connection.
        child_child_session.wait_for_disconnect()
        child_session.wait_for_disconnect()

    assert debug_session.read_json() == 'done'
示例#5
0
def test_multiprocessing(debug_session, pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        import multiprocessing
        import platform
        import sys
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        def child_of_child(q):
            print('entering child of child')
            assert q.get() == 2
            q.put(3)
            print('leaving child of child')

        def child(q):
            print('entering child')
            assert q.get() == 1

            print('spawning child of child')
            p = multiprocessing.Process(target=child_of_child, args=(q,))
            p.start()
            p.join()

            assert q.get() == 3
            q.put(4)
            print('leaving child')

        if __name__ == '__main__':
            import backchannel
            if sys.version_info >= (3, 4):
                multiprocessing.set_start_method('spawn')
            else:
                assert platform.system() == 'Windows'

            print('spawning child')
            q = multiprocessing.Queue()
            p = multiprocessing.Process(target=child, args=(q,))
            p.start()
            print('child spawned')
            backchannel.write_json(p.pid)

            q.put(1)
            assert backchannel.read_json() == 'continue'
            q.put(2)
            p.join()
            assert q.get() == 4
            q.close()
            backchannel.write_json('done')

    debug_session.initialize(multiprocess=True, target=(run_as, code_to_debug), start_method=start_method, use_backchannel=True)
    debug_session.start_debugging()

    root_start_request, = debug_session.all_occurrences_of(Request('launch') | Request('attach'))
    root_process, = debug_session.all_occurrences_of(Event('process'))
    root_pid = int(root_process.body['systemProcessId'])

    child_pid = debug_session.read_json()

    child_subprocess = debug_session.wait_for_next(Event('ptvsd_subprocess'))
    assert child_subprocess == Event('ptvsd_subprocess', {
        'rootProcessId': root_pid,
        'parentProcessId': root_pid,
        'processId': child_pid,
        'port': ANY.int,
        'rootStartRequest': {
            'seq': ANY.int,
            'type': 'request',
            'command': root_start_request.command,
            'arguments': root_start_request.arguments,
        }
    })
    child_port = child_subprocess.body['port']

    child_session = DebugSession(start_method=START_METHOD_CMDLINE, ptvsd_port=child_port)
    child_session.ignore_unobserved = debug_session.ignore_unobserved
    child_session.connect()
    child_session.handshake()
    child_session.start_debugging()

    debug_session.proceed()
    child_child_subprocess = debug_session.wait_for_next(Event('ptvsd_subprocess'))
    assert child_child_subprocess == Event('ptvsd_subprocess', {
        'rootProcessId': root_pid,
        'parentProcessId': child_pid,
        'processId': ANY.int,
        'port': ANY.int,
        'rootStartRequest': {
            'seq': ANY.int,
            'type': 'request',
            'command': root_start_request.command,
            'arguments': root_start_request.arguments,
        }
    })
    child_child_port = child_child_subprocess.body['port']

    child_child_session = DebugSession(start_method=START_METHOD_CMDLINE, ptvsd_port=child_child_port)
    child_child_session.ignore_unobserved = debug_session.ignore_unobserved
    child_child_session.connect()
    child_child_session.handshake()
    child_child_session.start_debugging(freeze=False)

    debug_session.write_json('continue')

    if sys.version_info >= (3,):
        child_child_session.wait_for_termination()
        child_session.wait_for_termination()
    else:
        # These should really be wait_for_termination(), but child processes don't send the
        # usual sequence of events leading to 'terminate' when they exit for some unclear
        # reason (ptvsd bug?). So, just wait till they drop connection.
        child_child_session.wait_for_disconnect()
        child_session.wait_for_disconnect()

    assert debug_session.read_json() == 'done'
    debug_session.wait_for_exit()