-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathshr_abort_mod.F90
160 lines (118 loc) · 5.48 KB
/
shr_abort_mod.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
module shr_abort_mod
! This module defines procedures that can be used to abort the model cleanly in a
! system-specific manner
!
! The public routines here are only meant to be used directly by shr_sys_mod. Other code
! that wishes to use these routines should use the republished names from shr_sys_mod
! (shr_sys_abort, shr_sys_backtrace). (This is for consistency with older code, from
! when these routines were defined in shr_sys_mod.)
use, intrinsic :: iso_fortran_env, only: output_unit, error_unit
use shr_kind_mod, only : shr_kind_in, shr_kind_cx
use shr_log_mod , only : s_logunit => shr_log_Unit
#ifdef CPRNAG
! NAG does not provide this as an intrinsic, but it does provide modules
! that implement commonly used POSIX routines.
use f90_unix_proc, only: abort
#endif
implicit none
! PUBLIC: Public interfaces
private
! The public routines here are only meant to be used directly by shr_sys_mod. Other code
! that wishes to use these routines should use the republished names from shr_sys_mod
! (shr_sys_abort, shr_sys_backtrace). (This is for consistency with older code, from
! when these routines were defined in shr_sys_mod.)
public :: shr_abort_abort ! abort a program
public :: shr_abort_backtrace ! print a backtrace, if possible
contains
!===============================================================================
subroutine shr_abort_abort(string,rc, line, file)
use esmf, only : ESMF_LOGWRITE, ESMF_LOGMSG_ERROR, ESMF_FINALIZE, ESMF_END_ABORT
! Consistent stopping mechanism
!----- arguments -----
character(len=*) , intent(in), optional :: string ! error message string
integer(shr_kind_in), intent(in), optional :: rc ! error code
integer(shr_kind_in), intent(in), optional :: line
character(len=*), intent(in), optional :: file
! Local version of the string.
! (Gets a default value if string is not present.)
character(len=shr_kind_cx) :: local_string
!-------------------------------------------------------------------------------
if (present(string)) then
local_string = trim(string)
else
local_string = "Unknown error submitted to shr_abort_abort."
end if
if(present(rc)) then
write(local_string, *) trim(local_string), ' rc=',rc
endif
call print_error_to_logs("ERROR", local_string)
call ESMF_LogWrite(local_string, ESMF_LOGMSG_ERROR, line=line, file=file)
call shr_abort_backtrace()
call ESMF_Finalize(endflag=ESMF_END_ABORT)
! A compiler's abort method may print a backtrace or do other nice
! things, but in fact we can rarely leverage this, because MPI_Abort
! usually sends SIGTERM to the process, and we don't catch that signal.
call abort()
end subroutine shr_abort_abort
!===============================================================================
!===============================================================================
subroutine shr_abort_backtrace()
! This routine uses compiler-specific facilities to print a backtrace to
! error_unit (standard error, usually unit 0).
#if defined(CPRIBM)
! This theoretically should be in xlfutility, but using it from that
! module doesn't seem to always work.
interface
subroutine xl_trbk()
end subroutine xl_trbk
end interface
call xl__trbk()
#elif defined(CPRGNU) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8 ))
! gfortran 4.8 and later implement this intrinsic. We explicitly call it
! out as such to make sure that it really is available, just in case the
! CPP logic above screws up.
intrinsic :: backtrace
call backtrace()
#elif defined(CPRINTEL)
! tracebackqq uses optional arguments, so *must* have an explicit
! interface.
use ifcore, only: tracebackqq
! An exit code of -1 is a special value that prevents this subroutine
! from aborting the run.
call tracebackqq(user_exit_code=-1)
#else
! Currently we have no means to request a backtrace from the NAG runtime,
! even though it is capable of emitting backtraces itself, if you use the
! "-gline" option.
! Similarly, PGI has a -traceback option, but no user interface for
! requesting a backtrace to be printed.
#endif
flush(error_unit)
end subroutine shr_abort_backtrace
!===============================================================================
!===============================================================================
subroutine print_error_to_logs(error_type, message)
! This routine prints error messages to s_logunit (which is standard output
! for most tasks in CESM) and also to standard error if s_logunit is a
! file.
!
! It also flushes these output units.
character(len=*), intent(in) :: error_type, message
integer, allocatable :: log_units(:)
integer :: i
if (s_logunit == output_unit .or. s_logunit == error_unit) then
! If the log unit number is standard output or standard error, just
! print to that.
allocate(log_units(1), source=[s_logunit])
else
! Otherwise print the same message to both the log unit and standard
! error.
allocate(log_units(2), source=[error_unit, s_logunit])
end if
do i = 1, size(log_units)
write(log_units(i),*) trim(error_type), ": ", trim(message)
flush(log_units(i))
end do
end subroutine print_error_to_logs
!===============================================================================
end module shr_abort_mod