-
Notifications
You must be signed in to change notification settings - Fork 62
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
UB in destruction order with global mpi::environment #92
Comments
Thanks, |
"Next week" is not over yet but I'll interpret it as a skip anyway. :-) |
Ok, finally have some time to look at it !! I suspect the "In the vast majority of Boost.MPI programs, an instance of mpi::environment will be declared in main at the very beginning of the program." was mean to be interpreted as "as opposed to another function." as it is mostly the boost MPI counter part of MPI_Init. So I'm all for one less crash but think the documentation should be specifically clear that mpi::environment (and probably Boost.MPI objects potentially depending on mpi::environment, which is most of them I guess) should not be made global. But maybe I missed something. |
That is indeed a very good point. And there is probably a reason why nobody has stumbled over this yet. I actually wrote a unit test with several BOOST_AUTO_TEST_CASEs and for this, it seemed very convenient to have a global environment. Of course, now that you mention it, it seems like a rather bad idea. :) I would definitely vote for a clear statement about this in the documentation. I don't suppose there is much we can do to prevent static or global instances of |
Documentation has been updated |
I noticed a problem in mpi::environment calling mpi_datatype_map::clear() of an already gone mpi_datatype_map. Consider the following working program:
The relevant thing that this program does is sends std::array<int, 3>s around. This creates an entry in the datatype_map with MPI_Type_create_struct.
Now, let's move the environment out of main's scope, i.e.:
The documentation [1] says: "In the vast majority of Boost.MPI programs, an instance of mpi::environment will be declared in main at the very beginning of the program." It does not forbid an environment in global scope. Nether does the documentation of environment [2].
However, the second program segfaults on my machine (boost 1.70.0, OpenMPI 3.1.3) with:
After some debugging, I find that the difference is the order of destructors of the environment and the datatype_cache defined in mpi_datatype_cache.cpp:
For version 1 it is:
And for version 2 it is:
So the static gets destructed before the global environment and, thus, environment::~environment() invokes UB. I suspect the reason for this is that the static is initialized on the first call to mpi_datatype_cache() which is after the initialization of the global environment variable in version 2. The reversed destruction, then, causes the above problem.
I did a quick test for a quick fix, namely pulling the mpi_datatype_map out of mpi_datatype_cache()'s scope, i.e. changing mpi_datatype_cache() to this:
(Although its semantic is now different, I kept the
static
because the fix should not require external linkage.)With this, the segfault is gone and the destruction order in version 2 is the same as in version 1.
I did not open a pull request yet because I wanted to discuss the fix first. Maybe someone has a better idea?
[1] https://www.boost.org/doc/libs/1_70_0/doc/html/mpi/tutorial.html
[2] https://www.boost.org/doc/libs/1_70_0/doc/html/boost/mpi/environment.html
The text was updated successfully, but these errors were encountered: