Python hangs up on returning from a function

2020-03-26 11:30发布

问题:

So say I have two functions in a fairly complicated Flask application. One function calls the other function.

def dispatch_unlock(...):
    # ... stuff ...
    log('dis start')
    # this routine just sends some data over a ZMQ IPC socket
    # in this scenario, the socket send will time out
    ret = acl.enqueue(unlock.id, endpoint_id, filter_entry['service_id'])
    log('dis end')
    return ret

def something_else(...);
    # ... stuff ...
    log('routecall start')
    ret = dispatch_unlock(unlock, endpoint_id, endpoint, f)
    log('routecall end')
    return ret

When something_else runs, the following output is produced:

routecall start
dis start
dis end

After that, it just hangs up. I tried dumping the Python stack traces but they show nothing useful. One stack trace is in the Werkzurg reloader and the other one is the stack trace leading up to the dumper invoked by SIGUSR1.

Can anyone suggest what the hell is going on? Is the Python call stack somehow getting corrupted?

Edit: Here is what pdb shows when I singlestep execution just before the return. Looks like the frame above the call frame of dispatch_unlock gets lost somehow.

> /SourceCache/Florence/lib/plugin/route.py(27)dispatch_unlock()
-> return ret
(Pdb) s
--Return--
> /SourceCache/Florence/lib/plugin/route.py(27)dispatch_unlock()->None
-> return ret
(Pdb) s

回答1:

"It's not a bug, it's a feature"

Python was hanging up when trying to garbage collect the objects and closing the ZMQ IPC socket which was not opened due to the endpoint not being there (which is normal, as I'm doing testing). Apparently, in this scenario, ZMQ is meant to hang up indefinitely (which took me a long time to figure out since this is not documented anywhere). This can be avoided by setting the LINGER property of the ZMQ socket, which resolved the issue.