-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pebble.concurrent.process can not be used dynamically #80
Comments
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
This is a fairly nasty can of worms. To better understand what is happening under the hood, we need to understand how multiprocessing works across multiple platforms. Currently, multiprocessing supports 3 process creation methods of which 2 are of interest to you (as you said in #76 to have a mac). Fork Posix standard process creation consists in cloning the parent process into a child which is the exact copy but with a separate memory address space. In our context, this implies that when we run our decorated function, we simply pass the reference to it and everything works fine. In fact, both your examples above work on Linux and on MAC prior to Python 3.8. Spawn NT operating systems do not support the When a new process is started, it begins as a blank one. A brand new Python interpreter is launched and the target function module is then loaded. As the function reference cannot be inherited, its name is passed instead. The interpreter looks up the name within the module and runs the function. This is where things get complicated. As we decorate the function, when the child invokes it, it actually runs the decorator anew and the cycle of life continues (if This is why we use a trampoline. The parent actually calls a trampoline function and not the decorated one. When the child process starts and imports the module, the decorator stores the real function reference into a This works but has certain drawbacks. Among those, the fact that we cannot support inner scoping with the Regarding the first issue instead (the dynamic use of the decorator) this is something I did not take into account and has been fixed. I will update the documentation to inform regarding this known limitation. |
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
Fix released in |
Reproducer:
This errors out with a traceback like:
The problem goes away if the
hello = pebble.concurrent.process(hello)
line is moved outside of the__name__ == "__main__"
guard (or if the decorator form is used).It seems the problem is that the handling in
pebble/pebble/concurrent/process.py
Lines 190 to 195 in dde8add
The reason I want to apply
pebble.concurrent.process
dynamically is that it allows passingdaemon=False
, which is a feature the process pool doesn't seem to offer (described more in #76). And the reason I don't have a simple callable that I can decorate with@pebble.concurrent.process
at the module level scope is that my callables are actually dynamically loaded entrypoints.The one-line fix in wimglenn@19bcc94 works for my use-case, but it makes a bunch of the tests fail in ways I couldn't understand, so it's probably not as simple as that.
I'm not sure what a fix here might look like, perhaps even just documenting the restricted situations in which these decorators can be used. There is an easy workaround: just defining a new module level wrapper function which accepts the dynamically generated callable and calls it, and then putting the decorator on that function instead.
The text was updated successfully, but these errors were encountered: