Fix async Python functors invoking from multiple C++ threads (#1587)#1595
Fix async Python functors invoking from multiple C++ threads (#1587)#1595wjakob merged 2 commits intopybind:masterfrom
Conversation
|
I'm a bit confused by the change, can you clarify? Specifically, I'm wondering if/why it is safe to |
|
FWIW what's also missing here is a testcase that would have lead to breakage in the previous implemenation. |
|
@wjakob Your first comment is absolutely right, I missed that point, s.t. all functors became single-shot (can be called only once and fail/crash 2nd time). Fixed that in next commit. Had to introduce local "function handle" struct with custom destructor. Seems that my code is working now. Considering testcase: I can write a Python test with statefull lambda, and it should crash Python (and I suppose we can't catch/prevent it in testing code) without this PR and work fine with it. |
e619e19 to
e3375b6
Compare
|
@wjakob I've made a test case and squashed [NOTE] test leads to segfault (on my machine) if run without latest commit (with previous |
e3375b6 to
296627b
Compare
|
@wjakob there seems to be a problem with ~func_handle() {
gil_scoped_acquire acq;
function kill_f(std::move(f));
}If I replace it with conventional Python API for acquiring GIL (straight from documentation): ~func_handle() {
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
{
function kill_f(std::move(f));
}
PyGILState_Release(gstate);
}then everything works without issues. |
3637a3c to
9a4eb75
Compare
|
Hello @wjakob @uentity, I've authored a separate PR #1556 which resolves the deadlock problem with Below is my summary of what I understand of the problems these PRs are trying to solve.
I would love to contribute in any way possible to help resolve these! |
|
Hi @davidhewitt! With you PR #1556 applied I can bring back my original implementation of ~func_handle() {
gil_scoped_acquire acq;
function kill_f(std::move(f));
}Very soon after I thought my issue #1587 is solved I've faced the issue of your PR #1556 and fixed it by replacing BTW can you give any comment on comparative "heaviness" of capturing GIL solutions I noted earlier? If I look at |
|
I understand NB I see that #1211 has just been merged which was exactly the same thing that I was trying to solve. So I think that |
9a4eb75 to
b66623f
Compare
| func_handle(const func_handle&) = default; | ||
| ~func_handle() { | ||
| gil_scoped_acquire acq; | ||
| function kill_f(std::move(f)); |
There was a problem hiding this comment.
It might be more clear to explicitly reset the function handle and decrease the reference count: f.release().dec_ref();
There was a problem hiding this comment.
@davidhewitt causes strange test failure on VS with Python 3.6 on x86 platform, so reverted back to original version.
Logs: https://ci.appveyor.com/project/wjakob/pybind11/builds/20894165
b66623f to
60decef
Compare
|
@wjakob style check is failing because of non-existent URL: |
60decef to
b66623f
Compare
|
I was also affected by this and your patch has unblocked me. Thank you @uentity! |
…1587) Ensure GIL is held during functor destruction.
|
@hammer498 you're welcome =) |
|
This looks good to me now. |
Ensure GIL is released after functor destructor finished (not only
during functor execution as in previous implementation).
This fixes #1587