Skip to content

Commit f83140b

Browse files
authored
add basic error handler functionality (#457)
* add basic error handler functionality * set default error handler to ERRORS_RETURN
1 parent 1666288 commit f83140b

File tree

9 files changed

+134
-9
lines changed

9 files changed

+134
-9
lines changed

deps/consts_microsoftmpi.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const MPI_MAXLOC = reinterpret(Cint, 0x5800000c)
3232
const MPI_REPLACE = reinterpret(Cint, 0x5800000d)
3333
const MPI_NO_OP = reinterpret(Cint, 0x5800000e)
3434

35+
const MPI_Errhandler = Cint
36+
const MPI_ERRORS_ARE_FATAL = Cint(0x54000000)
37+
const MPI_ERRORS_RETURN = Cint(0x54000001)
38+
3539
const MPI_Request = Cint
3640
const MPI_REQUEST_NULL = reinterpret(Cint, 0x2c000000)
3741

deps/consts_mpich.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ const MPI_COMM_NULL = Cint(67108864)
2020
const MPI_COMM_SELF = Cint(1140850689)
2121
const MPI_COMM_WORLD = Cint(1140850688)
2222

23+
const MPI_Errhandler = Cint
24+
const MPI_ERRORS_ARE_FATAL = Cint(0x54000000)
25+
const MPI_ERRORS_RETURN = Cint(0x54000001)
26+
2327
const MPI_Request = Cint
2428
const MPI_REQUEST_NULL = Cint(738197504)
2529

deps/consts_openmpi.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ const MPI_COMM_NULL = Cint(2)
2323
const MPI_COMM_SELF = Cint(1)
2424
const MPI_COMM_WORLD = Cint(0)
2525

26+
const MPI_Errhandler = Ptr{Cvoid}
27+
MPI_Errhandler_f2c(c::Cint) = ccall((:MPI_Errhandler_f2c,libmpi),MPI_Errhandler,(Cint,),c)
28+
const MPI_ERRORS_ARE_FATAL = Cint(1)
29+
const MPI_ERRORS_RETURN = Cint(2)
30+
2631
const MPI_Request = Ptr{Cvoid}
2732
MPI_Request_f2c(c::Cint) = ccall((:MPI_Request_f2c,libmpi),MPI_Request,(Cint,),c)
2833
const MPI_REQUEST_NULL = Cint(0)

deps/gen_consts.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ MPI_handle = [
9898
:MPI_COMM_SELF,
9999
:MPI_COMM_WORLD,
100100
],
101+
:MPI_Errhandler => [
102+
:MPI_ERRORS_ARE_FATAL,
103+
:MPI_ERRORS_RETURN,
104+
],
101105
:MPI_Request => [
102106
:MPI_REQUEST_NULL,
103107
],

docs/src/advanced.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,11 @@ MPI.Info
3232
MPI.infoval
3333
```
3434

35+
## Error handler objects
36+
37+
```@docs
38+
MPI.ErrorHandler
39+
MPI.get_errorhandler
40+
MPI.set_errorhandler!
41+
```
42+

src/MPI.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ include("collective.jl")
5151
include("topology.jl")
5252
include("onesided.jl")
5353
include("io.jl")
54+
include("errorhandler.jl")
5455
include("mpiexec_wrapper.jl")
5556

5657
include("deprecated.jl")

src/environment.jl

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,12 @@ end
6565

6666

6767
"""
68-
Init(;finalize_atexit=true)
68+
Init(;finalize_atexit=true, errors_return=true)
6969
70-
Initialize MPI in the current process, and if `finalize_atexit` is true and adds an
71-
`atexit` hook to call [`MPI.Finalize`](@ref) if it hasn't already been called.
70+
Initialize MPI in the current process. The keyword options:
71+
72+
- `finalize_atexit`: if true, adds an `atexit` hook to call [`MPI.Finalize`](@ref) if it hasn't already been called.
73+
- `errors_return`: if true, will set the default error handlers for [`MPI.COMM_SELF`](@ref) and [`MPI.COMM_WORLD`](@ref) to be `MPI.ERRORS_RETURN`. MPI errors will appear as Julia exceptions.
7274
7375
All MPI programs must contain exactly one call to `MPI.Init` or
7476
[`MPI.Init_thread`](@ref). In particular, note that it is not valid to call `MPI.Init` or
@@ -80,13 +82,16 @@ The only MPI functions that may be called before `MPI.Init`/`MPI.Init_thread` ar
8082
# External links
8183
$(_doc_external("MPI_Init"))
8284
"""
83-
function Init(;finalize_atexit=true)
85+
function Init(;finalize_atexit=true, errors_return=true)
8486
@mpichk ccall((:MPI_Init, libmpi), Cint, (Ptr{Cint},Ptr{Cint}), C_NULL, C_NULL)
8587
if finalize_atexit
8688
atexit(_finalize)
8789
end
8890

8991
run_init_hooks()
92+
if errors_return
93+
set_default_error_handler_return()
94+
end
9095
_warn_if_wrong_mpi()
9196
end
9297

@@ -119,13 +124,17 @@ end
119124

120125

121126
"""
122-
Init_thread(required::ThreadLevel; finalize_atexit=true)
127+
Init_thread(required::ThreadLevel; finalize_atexit=true, errors_return=true)
123128
124-
Initialize MPI and the MPI thread environment in the current process, and if
125-
`finalize_atexit` is true and adds an `atexit` hook to call [`MPI.Finalize`](@ref) if it
126-
hasn't already been called. The argument specifies the required level of threading
129+
Initialize MPI and the MPI thread environment in the current process. The argument specifies the required level of threading
127130
support, see [`ThreadLevel`](@ref).
128131
132+
The keyword options are:
133+
134+
- `finalize_atexit`: if true, adds an `atexit` hook to call [`MPI.Finalize`](@ref) if it hasn't already been called.
135+
- `errors_return`: if true, will set the default error handlers for [`MPI.COMM_SELF`](@ref) and [`MPI.COMM_WORLD`](@ref) to be `MPI.ERRORS_RETURN`. MPI errors will appear as Julia exceptions.
136+
137+
129138
The function will return the provided `ThreadLevel`, and values may be compared via
130139
inequalities, i.e.
131140
@@ -144,7 +153,7 @@ The only MPI functions that may be called before `MPI.Init`/`MPI.Init_thread` ar
144153
# External links
145154
$(_doc_external("MPI_Init_thread"))
146155
"""
147-
function Init_thread(required::ThreadLevel; finalize_atexit=true)
156+
function Init_thread(required::ThreadLevel; finalize_atexit=true, errors_return=true)
148157
r_provided = Ref{ThreadLevel}()
149158
# int MPI_Init_thread(int *argc, char ***argv, int required, int *provided)
150159
@mpichk ccall((:MPI_Init_thread, libmpi), Cint,
@@ -159,6 +168,9 @@ function Init_thread(required::ThreadLevel; finalize_atexit=true)
159168
atexit(_finalize)
160169
end
161170
run_init_hooks()
171+
if errors_return
172+
set_default_error_handler_return()
173+
end
162174
_warn_if_wrong_mpi()
163175
return provided
164176
end

src/errorhandler.jl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""
2+
MPI.Errhandler
3+
4+
An MPI error handler object. Currently only two are supported:
5+
6+
- `ERRORS_ARE_FATAL` (default): program will immediately abort
7+
- `ERRORS_RETURN`: program will throw an `MPIError`.
8+
"""
9+
@mpi_handle ErrorHandler MPI_Errhandler
10+
11+
const ERRORS_ARE_FATAL = _ErrorHandler(MPI_ERRORS_ARE_FATAL)
12+
const ERRORS_RETURN = _ErrorHandler(MPI_ERRORS_RETURN)
13+
14+
function free(errh::ErrorHandler)
15+
if !Finalized()
16+
# int MPI_Errhandler_free(MPI_Errhandler *errhandler)
17+
@mpichk ccall((:MPI_Errhandler_free, libmpi), Cint, (Ptr{MPI_Errhandler},), errh)
18+
end
19+
return nothing
20+
end
21+
22+
function set_default_error_handler_return()
23+
set_errorhandler!(COMM_SELF, ERRORS_RETURN)
24+
set_errorhandler!(COMM_WORLD, ERRORS_RETURN)
25+
end
26+
27+
"""
28+
MPI.get_errorhandler(comm::MPI.Comm)
29+
MPI.get_errorhandler(win::MPI.Win)
30+
MPI.get_errorhandler(file::MPI.File.FileHandle)
31+
32+
Get the current [`ErrorHandler`](@ref) for the relevant MPI object.
33+
34+
# See also
35+
- [`set_errorhandler!`](@ref)
36+
"""
37+
function get_errorhandler(comm::Comm)
38+
errh = ErrorHandler(ERRORS_ARE_FATAL.val)
39+
@mpichk ccall((:MPI_Comm_get_errhandler, libmpi), Cint, (MPI_Comm, Ptr{MPI_Errhandler}), comm, errh)
40+
finalizer(free, errh)
41+
return errh
42+
end
43+
function get_errorhandler(win::Win)
44+
errh = ErrorHandler(ERRORS_ARE_FATAL.val)
45+
@mpichk ccall((:MPI_Win_get_errhandler, libmpi), Cint, (MPI_Win, Ptr{MPI_Errhandler}), win, errh)
46+
return errh
47+
end
48+
function get_errorhandler(file::File.FileHandle)
49+
errh = ErrorHandler(ERRORS_ARE_FATAL.val)
50+
@mpichk ccall((:MPI_File_get_errhandler, libmpi), Cint, (MPI_File, Ptr{MPI_Errhandler}), file, errh)
51+
return errh
52+
end
53+
54+
"""
55+
MPI.set_errorhandler!(comm::MPI.Comm, errh::ErrorHandler)
56+
MPI.set_errorhandler!(win::MPI.Win, errh::ErrorHandler)
57+
MPI.set_errorhandler!(file::MPI.File.FileHandle, errh::ErrorHandler)
58+
59+
Set the [`ErrorHandler`](@ref) for the relevant MPI object.
60+
61+
# See also
62+
- [`get_errorhandler`](@ref)
63+
"""
64+
function set_errorhandler!(comm::Comm, errh::ErrorHandler)
65+
@mpichk ccall((:MPI_Comm_set_errhandler, libmpi), Cint, (MPI_Comm, MPI_Errhandler), comm, errh)
66+
return nothing
67+
end
68+
function set_errorhandler!(win::Win, errh::ErrorHandler)
69+
@mpichk ccall((:MPI_Win_set_errhandler, libmpi), Cint, (MPI_Win, MPI_Errhandler), win, errh)
70+
return nothing
71+
end
72+
function set_errorhandler!(file::File.FileHandle, errh::ErrorHandler)
73+
@mpichk ccall((:MPI_File_set_errhandler, libmpi), Cint, (MPI_File, MPI_Errhandler), file, errh)
74+
return nothing
75+
end
76+
77+

test/test_errorhandler.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using MPI, Test
2+
MPI.Init()
3+
4+
@test MPI.ERRORS_ARE_FATAL != MPI.ERRORS_RETURN
5+
@test MPI.get_errorhandler(MPI.COMM_SELF) == MPI.ERRORS_RETURN
6+
@test_throws MPI.MPIError MPI.Send(rand(10), 2, 0, MPI.COMM_SELF)
7+
8+
MPI.set_errorhandler!(MPI.COMM_SELF, MPI.ERRORS_ARE_FATAL)
9+
@test MPI.get_errorhandler(MPI.COMM_SELF) == MPI.ERRORS_ARE_FATAL
10+

0 commit comments

Comments
 (0)