Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

[WIP] Fixes issue with multi-threaded application suspend and resume. #108

Closed
wants to merge 2 commits into from

Conversation

karthiknadig
Copy link
Member

Checked with @DonJayamanne that this is the expected behavior for VSC, since it matches the old debugger behavior.

@int19h Let me know if there is a better way to manage waiting for all threads to suspend.

@@ -39,6 +40,12 @@
ptvsd_sys_exit_code = 0


# Setting the suspend policy for breakpoints here since pydevd does not expose this feature via CMD_SET_BREAK command
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we have bitten the bullet and vendored pydevd, can this be done in a less hacky way now that you can also change things on the pydevd side of things?

I'm thinking something along the lines of CMD_SET_BREAK_XML, which works same as the existing command, but takes its arguments as an XML blob for extensibility. And then we can add a new attribute for suspend policy there.

Copy link
Member Author

Choose a reason for hiding this comment

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

XML or JSON :)

Copy link
Member Author

Choose a reason for hiding this comment

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

I will take this as a separate work item. since this will be a pydev protocol change, and it impacts pydevd tests as well.

ptvsd/wrapper.py Outdated
@@ -544,7 +555,11 @@ def on_threads(self, request, args):

threads = []
for xthread in xthreads:
tid = self.thread_map.to_vscode(xthread['id'])
try:
tid = self.thread_map.to_vscode(xthread['id'], False)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you use autogen=False here, so that it's clearer what False means from glancing at the code.

Copy link
Contributor

Choose a reason for hiding this comment

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

(and ditto for other uses)

if self.suspending_threads_for_bp and \
self.vsc_breakpoint_tid and \
self.suspended_thread_count == len(self.thread_map.vscode_ids()):
self.send_event('stopped', reason='breakpoint', threadId=self.vsc_breakpoint_tid, allThreadsStopped=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused - shouldn't this be done in the handler for CMD_THREADS_SUSPENDED. where we know that all threads are stopped?

Copy link
Member Author

Choose a reason for hiding this comment

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

These events occur on multiple threads. I will reply back with the exact thread details tomorrow.

Copy link
Member Author

Choose a reason for hiding this comment

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

Here is a example of how the events appear to ptvsd. the suspending event and suspended event appear on main and worker threads. Also note that the Worker thread pid_19284_id_1512282591696 suspended after we received the suspended event.

Suspending event: Thread-5 pid_19284_id_1512282591696
Created : MainThread pid_19284_id_1512267175360
Created : ptvsd.EventLoop pid_19284_id_1512282287072
Created : ptvsd.Client pid_19284_id_1512282287688
Created : Thread-5 pid_19284_id_1512282591696
Suspended : None pid_19284_id_1512267175360
Suspended event: Thread-5 pid_19284_id_1512282591696
Suspended : None pid_19284_id_1512282591696

The advantage of having suspended and suspending events is that it allows us to identify if the suspend is actually breakpoint suspend or due to user requesting to pause. But I feel this is not reflected in the naming of those events.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, so then the suspended event can happen before all threads have actually been suspended? Wouldn't that make it essentially useless though?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep. The only useful event is suspending. The event name does not indicate its actual purpose, which is detect suspension of threads for breakpoint.

So, do you suggest any other alternatives? Is there a way we can use threading.Condition with the stack trace lock, to ensure that all threads have suspended and have stack_trace before we send the event to VS?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants