Skip to content

Conversation

@lukejriddle
Copy link
Contributor

api._settrace.called is intended to confirm that a process had been traced before. However, returning in a try block prevents the subsequent else block from executing, so api._settrace was not updating this flag.

This change just removes the return. api._settrace will still return None, as pydevd.settrace was returning None before.

@lukejriddle lukejriddle requested a review from a team as a code owner December 3, 2024 15:09
@rchiodo
Copy link
Contributor

rchiodo commented Dec 3, 2024

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Contributor

@rchiodo rchiodo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is causing attach tests to fail on Linux. Not sure why, but if you follow the directions in the CONTRIBUTING.md, you should be able to run the failing tests yourself.

@lukejriddle
Copy link
Contributor Author

Looking into the test failures now, but I'm not able to run them locally (on Linux). I get the error Could not find .so for attach to process.. Any ideas why? Seems like debugpy isn't building the attach .so when running tox.

Repro:

  1. Check out repo
  2. Make new python venv and pip install flake8 black tox
  3. Run python -m tox

@rchiodo
Copy link
Contributor

rchiodo commented Dec 3, 2024

Oh we changed the repository to not have the binaries checked in. You have to build pydevd first. Forgot about that. I should update the contributing.md.

Basically:

  • cd src/debugpy/_vendored/pydevd
  • Set PYTHONPATH=.
  • Run python build_tools/build.py

@lukejriddle
Copy link
Contributor Author

Still not able to get the tests working. That build script didn't seem to build the attach .so, so I manually ran pydevd_attach_to_process/linux_and_mac/compile.sh as well. This fixed the error of not finding the shared library, but now I get an opaque error about gdb having an exit code of 1.

@rchiodo
Copy link
Contributor

rchiodo commented Dec 3, 2024

This fixed the error of not finding the shared library, but now I get an opaque error about gdb having an exit code of 1.

That's likely the attach failing. You'll have to add extra logging to the attach code I'm guessing.

@rchiodo
Copy link
Contributor

rchiodo commented Dec 3, 2024

Debugging tests failures is all looking at log files. If there's not enough information, you add more logging. Attach happens in this code here:

int DoAttach(bool isDebug, const char *command, bool showDebugInfo)

You'd add more printfs and then rebuild the .so files again.

@lukejriddle
Copy link
Contributor Author

Okay, figured out why the tests are failing. In the test, multiple adapters are attached to the same PID as session1 and session2. Before our change, the check for _settrace.called would never pass, allowing this behavior. Now, attaching multiple adapters to the same PID is essentially forbidden.

This is likely how it should work, though, and has even been requested in a previous issue, since api.listen should only be called once-per-process.

I can update the test to expect this failure, if that works with you @rchiodo

@rchiodo
Copy link
Contributor

rchiodo commented Dec 4, 2024

I can update the test to expect this failure, if that works with you @rchiodo

I believe the test is trying to reattach. We definitely want that to work. Just allowing the failure would be incorrect. Maybe detach has to set the trace flag to false and then the test will pass.

@lukejriddle
Copy link
Contributor Author

@microsoft-github-policy-service agree company="Meta"

@lukejriddle
Copy link
Contributor Author

Okay, how about this? Changed from _settrace.called to _listen.called, since its the multiple invocations of listen that will cause the debuggee to hang; multiple calls to settrace don't, as demonstrated by the attach tests.

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

I think you need to run ruff? The linter is failing.

Not sure about using listen instead. Sounds plausible, but the old settrace check also made sure that connect wasn't called more than once. Although maybe connect being called more than once is fine-ish? Connect while you're actually debugging and then reconnect after disconnect should be okay, but connect and then connect again isnt.

But the original code was letting that happen anyway so maybe it's fine.

@lukejriddle
Copy link
Contributor Author

Whoops, did a typo, just pushed the fix as well as the lint issues.

As a follow up, I can look into preventing additional connect calls to the same process if the debuggee already has an adapter connected. Otherwise behavior is pretty much unchanged other than preventing listen from hanging a process

--
Btw, I'm not sure what's going on with tox/pytest, but there are some tests (like the ones in test_attach.py) that pass when run in series using -n0 but fail if taken by a worker. Not sure if it's a config issue on my part

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

Btw, I'm not sure what's going on with tox/pytest, but there are some tests (like the ones in test_attach.py) that pass when run in series using -n0 but fail if taken by a worker. Not sure if it's a config issue on my part

Pytest doesn't play well with the way debugpy is running. Timeouts and such are killing processes before they're done. Mostly only happens on windows though.

At least for me. But if the test passes with -n0, then it's safe to say you fixed something.

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@lukejriddle
Copy link
Contributor Author

Not sure about these test failures... test_attach_pid_client[str] passes but [int] fails. And only in some environments...: AttributeError: 'GdbRemoveReadlineFinder' object has no attribute 'find_spec'

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

Most of the tests are failing because of the new test:

             Traceback (most recent call last):
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\server\api.py", line 130, in debug
                 return func(address, settrace_kwargs, **kwargs)
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\server\api.py", line 144, in listen
                 raise RuntimeError("debugpy.listen() has already been called on this process")
             RuntimeError: debugpy.listen() has already been called on this process
             
             Stack where logged:
               File "C:\Users\VssAdministrator\AppData\Local\Temp\pytest-of-unknown\pytest-0\popen-gw2\test_multiple_listen_raises_ex0\code_to_debug.py", line 12, in <module>
                 debugpy.listen(address=(host, port))
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\public_api.py", line 31, in wrapper
                 return wrapped(*args, **kwargs)
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\server\api.py", line 132, in debug
                 log.reraise_exception("{0}() failed:", func.__name__, level="info")
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\common\log.py", line 222, in reraise_exception
                 _exception(format_string, *args, **kwargs)

I don't think it's raising a runtime error.

@lukejriddle
Copy link
Contributor Author

Hmmm, it looks like it is, from those logs. And we also see the expected listen_exception message sent through the backchannel:

I+00001.266: listen() failed:
             
             Traceback (most recent call last):
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\server\api.py", line 130, in debug
                 return func(address, settrace_kwargs, **kwargs)
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\server\api.py", line 144, in listen
                 raise RuntimeError("debugpy.listen() has already been called on this process")
             RuntimeError: debugpy.listen() has already been called on this process
             
             Stack where logged:
               File "C:\Users\VssAdministrator\AppData\Local\Temp\pytest-of-unknown\pytest-0\popen-gw0\test_multiple_listen_raises_ex0\code_to_debug.py", line 12, in <module>
                 debugpy.listen(address=(host, port))
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\public_api.py", line 31, in wrapper
                 return wrapped(*args, **kwargs)
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\server\api.py", line 132, in debug
                 log.reraise_exception("{0}() failed:", func.__name__, level="info")
               File "D:\a\1\s\.tox\py39\lib\site-packages\debugpy\common\log.py", line 222, in reraise_exception
                 _exception(format_string, *args, **kwargs)
             

D+00001.266: backchannel <-- listen_exception

If this backchannel message weren't received we'd see an AssertionError, not worker 'gw5' crashed while running 'tests/debugpy/test_attach.py::test_multiple_listen_raises_exception[program]'

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

Oh then it's crashing the debugger, it's not that it isn't sending it.

@lukejriddle
Copy link
Contributor Author

I can't repro these issues on Linux py3.10 or Mac py3.13. Can I add similar skip rules like the other tests in this file? https://github.com/microsoft/debugpy/blob/main/tests/debugpy/test_attach.py#L156

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

I can't repro these issues on Linux py3.10 or Mac py3.13. Can I add similar skip rules like the other tests in this file? https://github.com/microsoft/debugpy/blob/main/tests/debugpy/test_attach.py#L156

I think the root cause of those failures is just that pytest is flakey. Next run they'd likely pass. Ideally we'd make all of these things more deterministic.

I'd rather not skip them though cause eventually we end up skipping everything. Maybe a retry?

@lukejriddle
Copy link
Contributor Author

Yeah sounds good. Do I have permissions to retry?

@lukejriddle
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Commenter does not have sufficient privileges for PR 1751 in repo microsoft/debugpy

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@rchiodo
Copy link
Contributor

rchiodo commented Dec 5, 2024

Wait did you change anything with the new double listen test? I think the test has to somehow manage the debugger crashing. I don't see another test doing that but I think it might just work if you put a try except around the code like so:

try:
  with debug.Session() as session:
        session.open_backchannel()
        session.spawn_debuggee(
            [
                code_to_debug,
                host,
                port,
            ]
        )
        session.wait_for_adapter_socket()

        session.expect_server_socket()
        session.connect_to_adapter((host, port))
        with session.request_attach():
            pass
except:
   pass

And then assert that the backchannel got the exception.

@lukejriddle
Copy link
Contributor Author

Was able to repro locally. Updated the test to finish the lifecycle of the adapter, went from failing to passing so should hopefully work in the pipeline

@rchiodo
Copy link
Contributor

rchiodo commented Dec 6, 2024

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@rchiodo rchiodo merged commit 5014f25 into microsoft:main Dec 6, 2024
24 checks passed
@rchiodo
Copy link
Contributor

rchiodo commented Dec 6, 2024

Thanks for the work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants