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

multiprocessing not working while debugging (it works on terminal though) #1969

Closed
pfaz69 opened this issue Dec 4, 2019 · 7 comments
Closed

Comments

@pfaz69
Copy link

pfaz69 commented Dec 4, 2019

Issue Type: Bug

here's the Error Traceback:
Traceback (most recent call last):
File "/home/paolo/.vscode/extensions/ms-python.python-2019.11.50794/pythonFiles/lib/python/old_ptvsd/ptvsd/log.py", line 110, in g
return f(*args, **kwargs)
File "/home/paolo/.vscode/extensions/ms-python.python-2019.11.50794/pythonFiles/lib/python/old_ptvsd/ptvsd/pydevd_hooks.py", line 74, in start_client
sock, start_session = daemon.start_client((host, port))
File "/home/paolo/.vscode/extensions/ms-python.python-2019.11.50794/pythonFiles/lib/python/old_ptvsd/ptvsd/daemon.py", line 214, in start_client
with self.started():
File "/home/paolo/anaconda3/envs/tensorflow-cpu/lib/python3.7/contextlib.py", line 112, in enter
return next(self.gen)
File "/home/paolo/.vscode/extensions/ms-python.python-2019.11.50794/pythonFiles/lib/python/old_ptvsd/ptvsd/daemon.py", line 110, in started
self.start()
File "/home/paolo/.vscode/extensions/ms-python.python-2019.11.50794/pythonFiles/lib/python/old_ptvsd/ptvsd/daemon.py", line 145, in start
raise RuntimeError('already started')
RuntimeError: already started

I've also tried the advised fix of adding "subProcess: true" in the debugging configuration, and "multiprocessing.set_start_method('spawn', True)": no improvements.
This was working earlier (a few weeks ago).

Extension version: 2019.11.50794
VS Code version: Code 1.40.2 (f359dd69833dd8800b54d458f6d37ab7c78df520, 2019-11-25T14:54:40.719Z)
OS version: Linux x64 4.15.0-72-generic

System Info
Item Value
CPUs Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz (8 x 3755)
GPU Status 2d_canvas: enabled
flash_3d: enabled
flash_stage3d: enabled
flash_stage3d_baseline: enabled
gpu_compositing: enabled
metal: disabled_off
multiple_raster_threads: enabled_on
oop_rasterization: disabled_off
protected_video_decode: unavailable_off
rasterization: disabled_software
skia_renderer: disabled_off
surface_control: disabled_off
surface_synchronization: enabled_on
video_decode: unavailable_off
viz_display_compositor: enabled_on
viz_hit_test_surface_layer: disabled_off
webgl: enabled
webgl2: enabled
Load (avg) 2, 2, 1
Memory (System) 15.55GB (7.53GB free)
Process Argv --no-sandbox --unity-launch
Screen Reader no
VM 0%
@karthiknadig karthiknadig transferred this issue from microsoft/vscode-python Dec 4, 2019
@pfaz69 pfaz69 changed the title multiprocessing no longer working while debugging (it works on terminal though) multiprocessing not working while debugging (it works on terminal though) Dec 6, 2019
@int19h
Copy link
Contributor

int19h commented Dec 9, 2019

Can you tell more about the code that you're debugging? Is it explicitly starting multiple processes, or using some library that does?

@pfaz69
Copy link
Author

pfaz69 commented Dec 10, 2019

Hi int19h and thank you for your concern.

in the relevant file, first multiprocessing is included:

import multiprocessing
multiprocessing.set_start_method('spawn', True)
import multiprocessing.connection

then later in the code:

proc = multiprocessing.Process( target=my_function, args=(my_addr, my_buffer, my_class, kwargs))
proc.start()
listener = multiprocessing.connection.Listener(some_addr)
self.conn = listener.accept()

while debugging, "proc.start()" is where the program breaks when pressing f10 (step over).

However, I noticed that if I press f11 (step into) the cursor goes past that instruction but the program stops responding after "self.conn= listener.accept()", leaving in my working directory a file named after the string inside "my_addr"

Thanks again,
Pfaz69

@int19h
Copy link
Contributor

int19h commented Dec 10, 2019

Are you missing if __name__ == "__main__" around parts of that code, by chance? When using "spawn", the child process will have to import the module, which will cause all the code at top level to run if it's unguarded. Thus, set_start_method() as well as the process-spawning code should all be inside that check.

@pfaz69
Copy link
Author

pfaz69 commented Dec 11, 2019

Hi int19h,
not sure I understand your path of mind.
if __name__ == "__main__" is present at the beginning of my program, in a main entry function that calls the relevant function, i.e. the one with multiprocessing.Process(), etc in itself. Such "relevant function" is located in a different file, the one importing the multiprocessing module.
multiprocessing.set_start_method('spawn', True) was not present in my version, I've added that line hoping to fix the vscode debugging issue, after reading about this possible fix in other discussions.
Please note that this appears to be a vscode debugger issue. When I run my code in a terminal it works. I've also tried my code with pycharm and eclipse debuggers. In the pycharm case the debugger worked at the price of downgrading python to version 3.6 (from version 3.7). In the eclipse case the debugger works without issues whatsoever.
Hope this answer your question, but please don't esitate to correct me if I took a wrong turn.
Thank you for your help.
Pfaz69

@int19h
Copy link
Contributor

int19h commented Dec 11, 2019

There are several issues here.

The fundamental problem is that ptvsd 4.x does not support forking (#943). We have fixed this via #1706, and it will ship in ptvsd 5, but this is in testing at the moment.

set_start_method() makes multiprocessing use explicitly spawned subprocesses instead of forking even on Linux, where fork is otherwise the default. This allows ptvsd 4.x to debug them.

However, the behavior of multiprocessing is somewhat different between fork and spawn, due to their inherent behavior. In case of fork, the spawned subprocess already has all the same modules imported, and just continues running from that same point. But in case of spawn, it's a brand new process, so it has to re-import all the same modules to execute your function. If any of those modules have top-level code with side effects, that code will re-run in the child process. That's what necessitates the use of if __name__ == "__main"__.

Note that set_start_method() must also be under that check - otherwise it will fail inside the child process, and prevent it from running (since it already inherited a start method from the parent, and it cannot be changed). The code snippet in Python docs for multiprocessing gives an example of correct use.

BTW, the docs don't mention the second argument to set_start_method(). Looking at the source code for it, it basically overrides the "context has already been set" check. If you added to suppress that error message, that conceals the real problem - set_start_method() must be called before any child process is created, and the check is there to detect this. So if you were hitting the error, it's likely because the execution order caused set_start_method() to happen too late, e.g. due to the order of imports. You must ensure that set_start_method() gets called first.

@pfaz69
Copy link
Author

pfaz69 commented Dec 17, 2019

Thank you very much, int19h, for your detailed explanation.
If I understand it correctly, though, in order for this fix to work, I should move my multiprocessing code in my main module while now it resides in another file. Am I getting this right?
Very good to know that with the next VSC release the issue will be fixed for good.
Thanks,
Pfaz69

@int19h
Copy link
Contributor

int19h commented Jan 21, 2020

Please follow the instructions in #1706 (comment) to try the new debugger!

@int19h int19h closed this as completed Jan 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants