[CXX-90] Crash due to static initialization order fiasco in BSON implementation Created: 09/Nov/11 Updated: 08/Jan/24 Resolved: 02/Apr/14 |
|
| Status: | Closed |
| Project: | C++ Driver |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | legacy-0.8.0 |
| Type: | Bug | Priority: | Critical - P2 |
| Reporter: | Balint Szente | Assignee: | Mira Carey |
| Resolution: | Done | Votes: | 1 |
| Labels: | boost, bson, c++, client, crash, cxxmove, initialization, legacy-cxx, static, windows | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Microsoft Windows XP SP3 32 bit |
||
| Attachments: |
|
||||||||||||
| Issue Links: |
|
||||||||||||
| Server Compat: | 2.3 | ||||||||||||
| Description |
|
The actual BSON implementation assumes the following static initialization order: (static) global variables of Boost Thread implementation are initialized before MongoDB's global (static) variables. However, as you know it, the C/C++ standard does not guarantee this across different translation units. To give an example: What happens? I tracked down with OllyDbg the cause of the corruption: "); " ); Conclusion:
Possible solutions: I think the first two options can be dropped. It is too complicated to change the code and the logic of the C++ clases. Solution: ALWAYS use dynamic linking with Boost on Windows. This way it can be ensured that the DllMain of boost_thread, containing the initialization of the "current_thread_tls_init_flag", will be called BEFORE the initialization of mongoclient specific static data. Add to SConstruct: So you should drop/deny the mongoclient.lib to be linked statically with Boost. |
| Comments |
| Comment by Balint Szente [ 10/Apr/14 ] |
|
Hello Jason! Thank you for the update on this issue. I'm glad to hear this bug was been fixed. Not relying on boost::spirit definitely solves this problem. So it is OK from my part, I consider this bug fixed. On the other hand, it is good to avoid static initialization of complex objects in C++ when multiple translation units are involved, as Andy wrote in the second comment. Thank you, |
| Comment by Mira Carey [ 02/Apr/14 ] |
|
Given that the fiasco problem seems resolved to the best of my understanding, I'm closing this out now. If you have trouble in the future, please feel free to open a new ticket. |
| Comment by Mira Carey [ 18/Mar/14 ] |
|
The C++ driver no longer relies on boost::spirit for JSON parsing, so this particular initialization order fiasco should no longer be possible. Additionally, I've had a chance to run clang's address sanitizer with checks for additional fiasco's and haven't found any that aren't appropriately guarded. If you'd like to retest, or have additional concerns, I'm happy to continue the conversation. If not, I'll close this out in a couple of days as fixed. |
| Comment by Balint Szente [ 20/Dec/11 ] |
|
Indeed, this would be the best (and maybe the only) long term solution. Unfortunately, the static initializations in C++ are safe, if and only if they use functions/data from the same translation unit where they reside. Otherwise, you never know when you will encounter such a situation again. |
| Comment by Andy Schwerin [ 19/Dec/11 ] |
|
I actually think that option 1, not using fromjson in static initializers, is achievable. We should be out of the business of complex static initializers to begin with. A plausible solution, which I have used elsewhere, is to move startup-time initialization of complex objects into functions. Those functions are marked using some macro magic with their dependencies, and then a InitMongo() function gets placed at the top of main(), which walks the graph and runs the init functions in a topsort order. With a modicum of cleverness, systems like this aren't painful to work with. The only loss is that startup-initialized objects can no longer be declared as "const". This more general solution will hopefully also save us some future pain. |
| Comment by Balint Szente [ 10/Nov/11 ] |
|
How can I edit the description of this ticket to apply wiki formatting for better readability? |