-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
[BUG] TSAN error logs #2754
Comments
To link up things:
|
I knew I'd seen the other one as well:
|
I know this is the TSAN thread, but TSAN seems to be a major PITA to set up. I'm hoping no one would mind me submitting helgrind's analysis. https://gist.github.com/bstaletic/98441d24b5e0010118051c31036ef2f8 Note: debug symbols for all dependency are necessary to get useful tracebacks. Observation: |
The main issue with Helgrind (I've been playing around with it, a few days ago), is that it doesn't recognize C++'s Btw, the main issue (or one of the main issues) seems to lie in this line: pybind11/tests/test_iostream.cpp Line 40 in e612043
Apparently, |
@henryiii did someone already try out this suggestion in the meantime? |
The current implementation is exactly what is recommended. The "fully qualified virtual call" is at best the same, and possibly not really functional in forcing the correct call. Since it didn't fix the problem, I don't think there's any harm in moving to the fully qualified call, but there should not be a benefit. |
Do you think we could add a mutex here, perhaps? |
I really don't know, not knowing much about threading, but I'd be happy to try out ideas for you. If you point me to a branch with experimental changes it'll take me only a few minutes to try them out. |
@henryiii, @rwgk and I discussed this in a private chat, but we couldn't figure out who's job it is to have the mutex: the custom According to https://berthub.eu/articles/posts/iostreams-unexpected/ (quoting the standard), writing to |
Coincidentally I saw we're using the |
It's defined if Python was compiled with thread support. We could possibly add a mutex only if WITH_THREAD is defined? I tried to setup TSan, but getting it working on Python on macOS or in docker seems to be painful. |
In principle, even if Python doesn't have threads, a user could still start threads in C++-only code? So that feels tricky |
I can give you very quick feedback (most of the time), using our internal tools. I know it's not ideal to have me in the loop, but probably most practical to get rid of that annoying flake.
I'd say a problem for later. One at a time. |
This is part of figuring out the fix for our problem though. The actual issue in the tests is easy to fix: put a mutex around |
We already have a mutex of sorts with the gil_scoped_aquire? Are we really worried about performance here? Could we add a lock_guard there as well, possibly / probably including the setp, and maybe later improve performance? I haven't noticed the empty output error in a long while, roughly since the linked PR went in; this seems to have replaced it. :/ |
This is the same bug as in older versions, but instead of printing empty strings, it now hangs up... |
I believed I tried abusing the GIL as ad-hoc mutex, and that worked |
@jbms provided this information to me, posting here with his permission: In general iostream and streambuf objects are not thread-safe: However, there is an exception for the standard streams: if they are in "synchronized" mode: This is a bit of a weird guarantee, but that is what there is... There doesn't seem to be any explicit language about thread safety in the case that a different streambuf has been associated with std::cout, but given the design of c++ iostreams, I think all the customization happens via virtual methods of streambuf --- ostream itself does not have any virtual methods. Therefore it stands to reason that the synchronization logic happens in the default streambuf associated with std::cout, and if you change that, you also lose the synchronization. Indeed, looking at libc++, here is the definition of the streambuf backing std::cout: It appears that the way it achieves thread safety is by NOT setting a buffer on the streambuf. Since streambuf manipulates its internal buffer without locking, that isn't thread safe. But by not setting a buffer, all writes are immediately sent to the The pybind11 output redirect relies on this streambuf type: pybind11/include/pybind11/iostream.h Line 24 in 9b7bfef
It does set a buffer, which leads to streambuf manipulating the buffer in a thread-unsafe manner. I think it might be possible to make that thread safe by eliminating the buffer, similar to __stdoutbuf. I think the C++ standard still wouldn't guarantee thread safety in this case, but in practice it seems likely to work on all implementations --- I guess you could check what MSVC's standard library and libstdc++ do. Eliminating the buffering may hurt performance. Potentially there could be both a thread-safe and thread-unsafe pythonbuf implementation. |
Coincidentally, while UBSAN testing PR #2917 locally (against the
NOTE: It is NOT certain that this UBSAN error is meaningful or related to the TSAN error, but I'm attaching the traceback JIC it's giving someone a useful clue. |
TSAN logs as requested by @YannickJadoul here:
#2746 (comment)
Using
master
b7dfe5c+
#2409+
#2746 (YannickJadoul@727b3ae)+
2 additional minor local patches.test -c dbg --config=tsan
(Google-internal toolchain)Failing tests:
test_gil_scoped.py
[EDIT: see PR AddPYBIND11_SIMPLE_GIL_MANAGEMENT
option (cmake, C++ define) #4216]test_iostream.py
[EDIT: see PR Adding iostream.h thread-safety documentation. #2995]:pybind11/tests/test_iostream.cpp
Line 43 in d587a2f
The text was updated successfully, but these errors were encountered: