7

Env:

Ubuntu - 18.04
Python - 3.6.6
cx_Freeze - 6.1

Code:

Simple main_script.py file (example in repository - https://github.com/Yuriy-Leonov/cython_multiprocessing_issue )

import multiprocessing

if __name__ == '__main__':
    print("step-1")
    multiprocessing.set_start_method("spawn")
    print("step-2")
    multiprocessing.freeze_support()
    print("step-3")
    manager = multiprocessing.Manager()
    print("step-4")
    s_dict = manager.dict()
    print("finish")

And setup.py (for cx_Freeze):

import cx_Freeze

executables = [cx_Freeze.Executable("main_script.py")]

cx_Freeze.setup(
    name="Example",
    options={
        "build_exe": {
            "replace_paths": [("*", "")]
        },
    },
    executables=executables
)

Issue:

After building executable file via command python setup.py build I ran it and console log contained following:

step-1
step-2
step-3
step-1
step-2
step-3
step-1
step-2
step-3
...

And infinite processes are spawned.
I understand that multiprocessing.Manager() should spawn "server" process. But can't get clue of current behaviorand and how to force it to create "shared dict"

Important:

multiprocessing.set_start_method("spawn") can't be changed and required due to main program behavior.

Question:

How to achive of creating manager.dict() in current configuration?

PS:

There is no issue if run with regular python <filename>(obvious)

Yuriy Leonov
  • 536
  • 1
  • 9
  • 33
  • If it's a pure python script and compiling it with cython generates different runtime behavior than if you're running under a regular a python interpreter then I think it's by definition a bug in cython. – ngoldbaum Feb 14 '20 at 20:52
  • https://github.com/cython/cython/issues/3262 seems relevant – ngoldbaum Feb 14 '20 at 20:54
  • I have tried to improve my answer in https://stackoverflow.com/a/47360452/5769463. Because it applies to any frozen python script and not only Cython - it shows what is going wrong, references bug-entry which is not yet resolved and also proposes a do-it-yourself solution, which can at least serve as a good starting point. – ead Feb 16 '20 at 19:22

1 Answers1

0

It's important to understand what set_start_method("spawn") does.

It does not make sense to run your script as a pre-compiled executable and expect set_start_method("spawn") to just work, because "spawn" here means "start my child processes by reinvoking the interpreter", but the "interpreter" is your pre-compiled program!

When you run your program, you get a fork bomb because the multiprocessing module tries to spawn the following processes:

$ ./main_script --multiprocessing-fork tracker_fd=6 pipe_handle=8
$ ./main_script -S -E -c 'from multiprocessing.semaphore_tracker import main;main(5)'

That's not going to work with your pre-compiled program. You will need to explicitly exec into the python interpreter or handle these cases if you want set_start_method("spawn") to work.

Michael Graczyk
  • 4,905
  • 2
  • 22
  • 34