Ejemplo n.º 1
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'
Ejemplo n.º 2
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()