Comments you submit will be routed for moderation. If you have an account, please log in first.
Modify

Ticket #182 (closed defect: fixed)

Opened 3 years ago

Last modified 19 months ago

Multiprocessing code fails when using a onefile executable on win32

Reported by: jkp Owned by: htgoebel
Priority: high Milestone: PyInstaller 2.0
Component: PyInstaller Version: 1.4
Severity: critical Keywords: multiprocessing win32 onefile
Cc:

Description

I've had a problem for a long-while in some code that uses the multiprocessing module to co-oridinate multiple subprocesses. The code works fine without PyInstaller? involved, but when I package it as a PyInstaller? onefile executable I find that all kinds of errors are thrown when using cross-process constructs such as semaphores etc.

I spent some time tracking down the issue today have boiled it down to the following:

  • I've implemented a simple test script that when packaged as a onefile executable illustrates the problem.
  • The issue seems to be solveable by commenting out the line in launch.c that resets the _MEIPASS2 environment variable before running the packaged scripts. With this environment variable present PyInstaller? does not try to extract things again for subprocesses since this is already done (which seems like the correct behaviour).

The offending line was originally added here: http://www.pyinstaller.org/changeset/571. I'm not sure what the reasoning behind this existing is but it certainly breaks multiprocessing. Is there a better solution that I don't know of? Why is this line required?

I've attached the testcase code so that someone else can reproduce the issue and perhaps suggest what should be done.

http://www.pyinstaller.org/changeset/571

Attachments

main.py (1.1 KB) - added by jkp 3 years ago.
Test case that illustrates the issue
test_multiprocess.py (516 bytes) - added by matysek 20 months ago.
Another multiprocess example
test_multiprocess_2.2.py (827 bytes) - added by htgoebel 20 months ago.
test_multiprocess.py with an idea of an work-around
test_multiprocess_2_3.py (982 bytes) - added by matysek 20 months ago.
workaround that should work on winxp

Change History

Changed 3 years ago by jkp

Test case that illustrates the issue

comment:1 Changed 2 years ago by matysek

  • Milestone set to PyInstaller 1.6

Thanks for the report. When this is fixed we should create a buildtest from the attached script.

comment:2 Changed 20 months ago by matysek

Does it work when using the function multiprocessing.freeze_support()?

Changed 20 months ago by matysek

Another multiprocess example

comment:3 Changed 20 months ago by matysek

  • Owner changed from giovannibajo to matysek
  • Status changed from new to assigned

This issue is still present.

We should find a way how to allow running pyinstaller apps by pyinstaller apps and at the same time not breaking multiprocess module.

comment:4 Changed 20 months ago by htgoebel

This problem should only occur in Windows, where the process is re-started for each Process. On other systems, fork() is used.

_MEIPASS2 is used as an indicator whether the files have already been unpacked.

r571 seams to solve an issue occurring when running the program again for cases where it has to be unpacked again. (I'm unsure about which cases this really requires, but this is another issue).

I'm afraid, this can not be solved within PyInstaller?, but has to be solved in multiprocessing. Any try to solve it in PyInstaller? would in fact undo r571.

multiprocess need to set _MEIPASS2 before spawning and needs to unset just after.

Changed 20 months ago by htgoebel

test_multiprocess.py with an idea of an work-around

comment:5 Changed 20 months ago by matysek

  • Owner changed from matysek to htgoebel
  • Status changed from assigned to new

Changed 20 months ago by matysek

workaround that should work on winxp

comment:6 Changed 19 months ago by htgoebel

  • Status changed from new to closed
  • Resolution set to fixed

Martin solved this issue, resolution is documented in http://www.pyinstaller.org/wiki/Recipe/Multiprocessing

comment:7 Changed 19 months ago by matysek

  • Priority changed from highest to high
  • Status changed from closed to reopened
  • Resolution fixed deleted
  • Severity changed from blocker to critical

Reopening since there is still an issue. The main process is not waiting for child (multiprocess) processes.

comment:8 Changed 19 months ago by htgoebel

Solution is found: It requieres more code in main, see Recipe/Multiprocessing.

http://www.pyinstaller.org/wiki/Recipe/Multiprocessing

But still some work to be done:

Getting the value from PYTHONPATH will fail if sys.path was changed in the meantime. I propose changing the loader to store the value somewhere else. E.e. in sys._MEIPASS.

comment:9 follow-up: ↓ 10 Changed 19 months ago by matysek

We could unset the _MEIPASS during bootstrap process instead doing directly in bootloader. Then when unsetting _MEIPASS we could set sys._MEIPASS afterwards.

comment:10 in reply to: ↑ 9 Changed 19 months ago by htgoebel

Replying to matysek:

We could unset the _MEIPASS during bootstrap process instead doing directly in bootloader. Then when unsetting _MEIPASS we could set sys._MEIPASS afterwards.

Good idea. Moving as much logic into Python code as possible eases maintenance.

comment:11 Changed 19 months ago by matysek

  • Status changed from reopened to closed
  • Resolution set to fixed

sys._MEIPASS is implemented and reseted in python code.

comment:12 Changed 19 months ago by htgoebel

see r1680 and r1683

View

Add a comment

Modify Ticket

Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.