Skip to content
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

multiprocessing.SyncManager connection hang #60118

Closed
palmer mannequin opened this issue Sep 10, 2012 · 9 comments
Closed

multiprocessing.SyncManager connection hang #60118

palmer mannequin opened this issue Sep 10, 2012 · 9 comments
Labels
type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@palmer
Copy link
Mannequin

palmer mannequin commented Sep 10, 2012

BPO 15914
Nosy @brettcannon, @ncoghlan, @applio

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2015-02-13.17:17:30.330>
created_at = <Date 2012-09-10.21:29:47.733>
labels = ['type-crash']
title = 'multiprocessing.SyncManager connection hang'
updated_at = <Date 2015-02-13.17:17:30.329>
user = 'https://bugs.python.org/palmer'

bugs.python.org fields:

activity = <Date 2015-02-13.17:17:30.329>
actor = 'brett.cannon'
assignee = 'none'
closed = True
closed_date = <Date 2015-02-13.17:17:30.330>
closer = 'brett.cannon'
components = []
creation = <Date 2012-09-10.21:29:47.733>
creator = 'palmer'
dependencies = []
files = []
hgrepos = []
issue_num = 15914
keywords = []
message_count = 9.0
messages = ['170240', '170313', '170314', '170320', '170325', '235766', '235834', '235878', '235906']
nosy_count = 5.0
nosy_names = ['brett.cannon', 'ncoghlan', 'sbt', 'palmer', 'davin']
pr_nums = []
priority = 'normal'
resolution = 'fixed'
stage = None
status = 'closed'
superseder = None
type = 'crash'
url = 'https://bugs.python.org/issue15914'
versions = ['Python 3.2']

@palmer
Copy link
Mannequin Author

palmer mannequin commented Sep 10, 2012

create.py:

import multiprocessing
manager = multiprocessing.Manager()
namespace = manager.Namespace()
print("create.py complete")

run.py:

import create
print("run.py complete")

Correct behaviour occurs for create.py:

$ python3 create.py
create.py complete

INCORRECT behaviour occurs for run.py:

$ python3 run.py

No output, because it hangs. On SIGINT:

^CTraceback (most recent call last):
  File "run.py", line 1, in <module>
    import create
  File "[...]/create.py", line 7, in <module>
    test()
  File "[...]/create.py", line 5, in test
    namespace = manager.Namespace()
  File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/multiprocessing/managers.py", line 670, in temp
    token, exp = self._create(typeid, *args, **kwds)
  File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/multiprocessing/managers.py", line 568, in _create
    conn = self._Client(self._address, authkey=self._authkey)
  File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/multiprocessing/connection.py", line 175, in Client
    answer_challenge(c, authkey)
  File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/multiprocessing/connection.py", line 412, in answer_challenge
    message = connection.recv_bytes(256)         # reject large message
KeyboardInterrupt
$ python3
Python 3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin

This appears to be a duplicate of this *closed* bug:

http://bugs.python.org/issue7474

This was closed because nobody could reproduce the behaviour on Python 3. I have reproduced it, but I don't know how to reopen that bug, so I'm filing this one. The test case in 7474 also fails for me.

@palmer palmer mannequin added the type-crash A hard crash of the interpreter, possibly with a core dump label Sep 10, 2012
@sbt
Copy link
Mannequin

sbt mannequin commented Sep 11, 2012

I get the same hang on Linux with Python 3.2.

For Windows the documentation does warn against starting a process as a side effect of importing a process. There is no explicit warning for Unix, but I would still consider it bad form to do such things as a side effect of importing a module.

It appears that it is the import of the hmac module inside deliver_challenge() that is hanging. I expect forking a process while an import is in progress may cause the import machinery (which I am not familiar with) to be in an inconsistent state. The import lock should have been reset automatically after the fork, but maybe that is not enough. Maybe the fact that the import is being done by a non-main thread is relevant.

I would suggest just rewriting the code as

create.py:

import multiprocessing

def main():
    manager = multiprocessing.Manager()
    namespace = manager.Namespace()
    print("create.py complete")

if __name__ == '__main__':
    main()

run.py:

import create
create.main()
print("run.py complete")

@sbt
Copy link
Mannequin

sbt mannequin commented Sep 11, 2012

Here is a reproduction without using multiprocessing:

create.py:

import threading, os

def foo():
    print("Trying import")
    import sys
    print("Import successful")

pid = os.fork()
if pid == 0:
    try:
        t = threading.Thread(target=foo)
        t.start()
        t.join()
    finally:
        os._exit(0)

os.waitpid(pid, 0)
print("create.py complete")

run.py:

import create
print("run.py complete")

Using python2.7 and python3.3 this works as expected, but with python3.2 I get

user@mint-vm /tmp $ python3 create.py
Trying import
Import successful
create.py complete
user@mint-vm /tmp $ python3 run.py 
Trying import
<Hang>
^CTraceback (most recent call last):
  File "run.py", line 1, in <module>
    import create
  File "/tmp/create.py", line 17, in <module>
    os.waitpid(pid, 0)
KeyboardInterrupt

@sbt sbt mannequin added type-bug An unexpected behavior, bug, or error and removed type-crash A hard crash of the interpreter, possibly with a core dump labels Sep 11, 2012
@sbt
Copy link
Mannequin

sbt mannequin commented Sep 11, 2012

Python 3.2 has extra code in _PyImport_ReInitLock() which means that when a fork happens as a side effect of an import, the main thread of the forked process owns the import lock. Therefore other threads in the forked process cannot import anything.

_PyImport_ReInitLock(void)
{
    if (import_lock != NULL)
        import_lock = PyThread_allocate_lock();
    if (import_lock_level > 1) {
        /* Forked as a side effect of import */
        long me = PyThread_get_thread_ident();
        PyThread_acquire_lock(import_lock, 0);
        /* XXX: can the previous line fail? */
        import_lock_thread = me;
        import_lock_level--;
    } else {
        import_lock_thread = -1;
        import_lock_level = 0;
    }
}

I think the reason this code is not triggered in Python 3.3 is the introduction of per-module import locks.

@sbt sbt mannequin added type-crash A hard crash of the interpreter, possibly with a core dump and removed type-bug An unexpected behavior, bug, or error labels Sep 11, 2012
@sbt
Copy link
Mannequin

sbt mannequin commented Sep 11, 2012

It looks like the problem was caused be the fix for

http://bugs.python.org/issue9573

I think the usage this was intended to enable is evil since one of the forked processes should always be terminated with os._exit().

@applio
Copy link
Member

applio commented Feb 11, 2015

Adding Brett Cannon as this issue appears to really be about doing an import shortly after an os.fork() -- this may be of particular interest to him.

This issue probably should have had Brett and/or others added to nosy long ago.

@brettcannon
Copy link
Member

I'm adding Nick to see if he has anything to add since he was the one that worked on the change that Richard said caused the problem. But in my opinion this is in the same realm as importing as a side-effect of spawning a thread; don't do it.

@ncoghlan
Copy link
Contributor

3.2 is in security-fix only mode, so nothing's going to change there.

For 3.3+, the per-module import lock design means the issue doesn't happen.

However, I wonder if there may be some now dead code relating to the global import lock that could be deleted.

@brettcannon
Copy link
Member

Dead code deletion should be a separate issue, so I'm going to close this as fixed.

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-crash A hard crash of the interpreter, possibly with a core dump
Projects
None yet
Development

No branches or pull requests

3 participants