Skip to content

Commit 9b1f5e3

Browse files
authored
Merge pull request #208 from barche/auto-finalize
Optionally call MPI.Finalize at exit
2 parents 4070fbc + 091ba7b commit 9b1f5e3

File tree

7 files changed

+61
-3
lines changed

7 files changed

+61
-3
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ able to run the MPI job as expected, e.g., with
8787

8888
`mpirun -np 3 julia 01-hello.jl`
8989

90+
### Cleanup
91+
In Julia code building on this package, it may happen that you want to run MPI cleanup functions in a finalizer.
92+
This makes it impossible to manually call `MPI.Finalize()`, since the Julia finalizers may run after this call.
93+
To solve this, a C `atexit` hook to run `MPI.Finalize()` can be set using `MPI.finalize_atexit()`. It is possible
94+
to check if this function was called by checking the global `Ref` `MPI.FINALIZE_ATEXIT`.
95+
9096
## Usage : MPI and Julia parallel constructs together
9197

9298
In order for MPI calls to be made from a Julia cluster, it requires the use of

deps/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,13 @@ endif(UNIX)
202202

203203
add_dependencies(dist version)
204204

205-
add_library(juliampi SHARED test_mpi.f90)
205+
add_library(juliampi SHARED juliampi.c test_mpi.f90)
206206

207207
if(MPI_Fortran_LINK_FLAGS)
208208
set_target_properties(juliampi PROPERTIES LINK_FLAGS ${MPI_Fortran_LINK_FLAGS})
209209
endif(MPI_Fortran_LINK_FLAGS)
210210

211-
target_link_libraries(juliampi ${MPI_Fortran_LIBRARIES})
211+
target_link_libraries(juliampi ${MPI_C_LIBRARIES} ${MPI_Fortran_LIBRARIES})
212212

213213
include(CheckFunctionExists)
214214
set(CMAKE_REQUIRED_LIBRARIES ${MPI_C_LIBRARIES})

deps/juliampi.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <stdlib.h>
2+
#include <mpi.h>
3+
4+
void finalize_atexit()
5+
{
6+
int iflag, fflag;
7+
MPI_Initialized(&iflag);
8+
MPI_Finalized(&fflag);
9+
if (iflag && !fflag)
10+
{
11+
MPI_Finalize();
12+
}
13+
}
14+
15+
int install_finalize_atexit_hook()
16+
{
17+
return atexit(finalize_atexit);
18+
}

src/mpi-base.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,25 @@ function Finalize()
194194
ccall(MPI_FINALIZE, Void, (Ptr{Cint},), &0)
195195
end
196196

197+
const FINALIZE_ATEXIT = Ref(false)
198+
199+
"""
200+
finalize_atexit()
201+
202+
Indicate that MPI.Finalize() should be called automatically at exit, if not called manually already.
203+
The global variable `FINALIZE_ATEXIT` indicates if this function was called.
204+
"""
205+
function finalize_atexit()
206+
if is_windows()
207+
error("finalize_atexit is not supported on Windows")
208+
end
209+
ret = ccall(:install_finalize_atexit_hook, Cint, ())
210+
if ret != 0
211+
error("Failed to set finalize_atexit")
212+
end
213+
FINALIZE_ATEXIT[] = true
214+
end
215+
197216
function Abort(comm::Comm, errcode::Integer)
198217
ccall(MPI_ABORT, Void, (Ptr{Cint}, Ptr{Cint}, Ptr{Cint}),
199218
&comm.val, &errcode, &0)

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ singlefiles = ["test_spawn.jl"]
2222

2323
excludedfiles = []
2424
if is_windows()
25-
excludedfiles = ["test_info.jl", "test_onesided.jl"]
25+
excludedfiles = ["test_info.jl", "test_onesided.jl", "test_finalize_atexit.jl"]
2626
if Sys.WORD_SIZE == 32
2727
push!(excludedfiles, "test_spawn.jl")
2828
end

test/test_basic.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ MPI.Init()
77

88
@test MPI.Comm(MPI.CComm(MPI.COMM_WORLD)).val == MPI.COMM_WORLD.val
99

10+
if !is_windows()
11+
MPI.finalize_atexit()
12+
@test MPI.FINALIZE_ATEXIT[]
13+
end
14+
1015
@test !MPI.Finalized()
1116
MPI.Finalize()
1217
@test MPI.Finalized()

test/test_finalize_atexit.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Base.Test
2+
using MPI
3+
4+
@test !MPI.Initialized()
5+
MPI.Init()
6+
MPI.finalize_atexit()
7+
@test MPI.FINALIZE_ATEXIT[]
8+
9+
@test MPI.Initialized()
10+
@test !MPI.Finalized()

0 commit comments

Comments
 (0)