• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37527

pending completion
#37527

push

local

web-flow
make `IRShow.method_name` inferrable (#49607)

18 of 18 new or added lines in 3 files covered. (100.0%)

68710 of 81829 relevant lines covered (83.97%)

33068903.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.58
/base/error.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
# pseudo-definitions to show how everything behaves
4
#
5
# throw(label, val) = # throw a value to a dynamically enclosing block
6
#
7
# function rethrow(val)
8
#     global current_exception = val
9
#     throw(current_handler(), current_exception)
10
# end
11
#
12
# rethrow() = rethrow(current_exception)
13
#
14
# function throw(val)
15
#     global catch_backtrace = backtrace()
16
#     rethrow(val)
17
# end
18

19
"""
20
    throw(e)
21

22
Throw an object as an exception.
23

24
See also: [`rethrow`](@ref), [`error`](@ref).
25
"""
26
throw
27

28
## native julia error handling ##
29

30
"""
31
    error(message::AbstractString)
32

33
Raise an `ErrorException` with the given message.
34
"""
35
error(s::AbstractString) = throw(ErrorException(s))
5,404✔
36

37
"""
38
    error(msg...)
39

40
Raise an `ErrorException` with the given message.
41
"""
42
function error(s::Vararg{Any,N}) where {N}
288✔
43
    @noinline
10✔
44
    throw(ErrorException(Main.Base.string(s...)))
288✔
45
end
46

47
"""
48
    rethrow()
49

50
Rethrow the current exception from within a `catch` block. The rethrown
51
exception will continue propagation as if it had not been caught.
52

53
!!! note
54
    The alternative form `rethrow(e)` allows you to associate an alternative
55
    exception object `e` with the current backtrace. However this misrepresents
56
    the program state at the time of the error so you're encouraged to instead
57
    throw a new exception using `throw(e)`. In Julia 1.1 and above, using
58
    `throw(e)` will preserve the root cause exception on the stack, as
59
    described in [`current_exceptions`](@ref).
60
"""
61
rethrow() = ccall(:jl_rethrow, Bottom, ())
8,150✔
62
rethrow(@nospecialize(e)) = ccall(:jl_rethrow_other, Bottom, (Any,), e)
77✔
63

64
struct InterpreterIP
65
    code::Union{CodeInfo,Core.MethodInstance,Nothing}
2,421✔
66
    stmt::Csize_t
67
    mod::Union{Module,Nothing}
68
end
69

70
# convert dual arrays (raw bt buffer, array of GC managed values) to a single
71
# array of locations
72
function _reformat_bt(bt::Array{Ptr{Cvoid},1}, bt2::Array{Any,1})
536✔
73
    ret = Vector{Union{InterpreterIP,Ptr{Cvoid}}}()
536✔
74
    i, j = 1, 1
×
75
    while i <= length(bt)
60,483✔
76
        ip = bt[i]::Ptr{Cvoid}
59,947✔
77
        if UInt(ip) != (-1 % UInt) # See also jl_bt_is_native
59,947✔
78
            # native frame
79
            push!(ret, ip)
57,526✔
80
            i += 1
57,526✔
81
            continue
57,526✔
82
        end
83
        # Extended backtrace entry
84
        entry_metadata = reinterpret(UInt, bt[i+1])::UInt
2,421✔
85
        njlvalues =  entry_metadata & 0x7
2,421✔
86
        nuintvals = (entry_metadata >> 3) & 0x7
2,421✔
87
        tag       = (entry_metadata >> 6) & 0xf
2,421✔
88
        header    =  entry_metadata >> 10
2,421✔
89
        if tag == 1 # JL_BT_INTERP_FRAME_TAG
2,421✔
90
            code = bt2[j]::Union{CodeInfo,Core.MethodInstance,Nothing}
2,421✔
91
            mod = njlvalues == 2 ? bt2[j+1]::Union{Module,Nothing} : nothing
2,421✔
92
            push!(ret, InterpreterIP(code, header, mod))
4,842✔
93
        else
94
            # Tags we don't know about are an error
95
            throw(ArgumentError("Unexpected extended backtrace entry tag $tag at bt[$i]"))
×
96
        end
97
        # See jl_bt_entry_size
98
        j += Int(njlvalues)
2,421✔
99
        i += 2 + Int(njlvalues + nuintvals)
2,421✔
100
    end
59,947✔
101
    ret
536✔
102
end
103

104
"""
105
    backtrace()
106

107
Get a backtrace object for the current program point.
108
"""
109
function backtrace()
41✔
110
    @noinline
×
111
    # skip frame for backtrace(). Note that for this to work properly,
112
    # backtrace() itself must not be interpreted nor inlined.
113
    skip = 1
×
114
    bt1, bt2 = ccall(:jl_backtrace_from_here, Ref{SimpleVector}, (Cint, Cint), false, skip)
82✔
115
    return _reformat_bt(bt1::Vector{Ptr{Cvoid}}, bt2::Vector{Any})
41✔
116
end
117

118
"""
119
    catch_backtrace()
120

121
Get the backtrace of the current exception, for use within `catch` blocks.
122
"""
123
function catch_backtrace()
76✔
124
    bt, bt2 = ccall(:jl_get_backtrace, Ref{SimpleVector}, ())
152✔
125
    return _reformat_bt(bt::Vector{Ptr{Cvoid}}, bt2::Vector{Any})
76✔
126
end
127

128
struct ExceptionStack <: AbstractArray{Any,1}
129
    stack::Array{Any,1}
267✔
130
end
131

132
"""
133
    current_exceptions(task::Task=current_task(); [backtrace::Bool=true])
134

135
Get the stack of exceptions currently being handled. For nested catch blocks
136
there may be more than one current exception in which case the most recently
137
thrown exception is last in the stack. The stack is returned as an
138
`ExceptionStack` which is an AbstractVector of named tuples
139
`(exception,backtrace)`. If `backtrace` is false, the backtrace in each pair
140
will be set to `nothing`.
141

142
Explicitly passing `task` will return the current exception stack on an
143
arbitrary task. This is useful for inspecting tasks which have failed due to
144
uncaught exceptions.
145

146
!!! compat "Julia 1.7"
147
    This function went by the experimental name `catch_stack()` in Julia
148
    1.1–1.6, and had a plain Vector-of-tuples as a return type.
149
"""
150
function current_exceptions(task::Task=current_task(); backtrace::Bool=true)
686✔
151
    raw = ccall(:jl_get_excstack, Any, (Any,Cint,Cint), task, backtrace, typemax(Cint))::Vector{Any}
234✔
152
    formatted = Any[]
233✔
153
    stride = backtrace ? 3 : 1
233✔
154
    for i = reverse(1:stride:length(raw))
447✔
155
        exc = raw[i]
420✔
156
        bt = backtrace ? Base._reformat_bt(raw[i+1],raw[i+2]) : nothing
420✔
157
        push!(formatted, (exception=exc,backtrace=bt))
420✔
158
    end
626✔
159
    ExceptionStack(formatted)
233✔
160
end
161

162
## keyword arg lowering generates calls to this ##
163
function kwerr(kw, args::Vararg{Any,N}) where {N}
5✔
164
    @noinline
5✔
165
    throw(MethodError(Core.kwcall, (kw, args...)))
5✔
166
end
167

168
## system error handling ##
169
"""
170
    systemerror(sysfunc[, errno::Cint=Libc.errno()])
171
    systemerror(sysfunc, iftrue::Bool)
172

173
Raises a `SystemError` for `errno` with the descriptive string `sysfunc` if `iftrue` is `true`
174
"""
175
systemerror(p, b::Bool; extrainfo=nothing) = b ? systemerror(p, extrainfo=extrainfo) : nothing
339,786✔
176
systemerror(p, errno::Cint=Libc.errno(); extrainfo=nothing) = throw(Main.Base.SystemError(string(p), errno, extrainfo))
33✔
177

178
## system errors from Windows API functions
179
struct WindowsErrorInfo
180
    errnum::UInt32
181
    extrainfo
182
end
183
"""
184
    windowserror(sysfunc[, code::UInt32=Libc.GetLastError()])
185
    windowserror(sysfunc, iftrue::Bool)
186

187
Like [`systemerror`](@ref), but for Windows API functions that use [`GetLastError`](@ref Base.Libc.GetLastError) to
188
return an error code instead of setting [`errno`](@ref Base.Libc.errno).
189
"""
190
windowserror(p, b::Bool; extrainfo=nothing) = b ? windowserror(p, extrainfo=extrainfo) : nothing
×
191
windowserror(p, code::UInt32=Libc.GetLastError(); extrainfo=nothing) = throw(Main.Base.SystemError(string(p), 0, WindowsErrorInfo(code, extrainfo)))
×
192

193

194
## assertion macro ##
195

196

197
"""
198
    @assert cond [text]
199

200
Throw an [`AssertionError`](@ref) if `cond` is `false`. Preferred syntax for writing assertions.
201
Message `text` is optionally displayed upon assertion failure.
202

203
!!! warning
204
    An assert might be disabled at various optimization levels.
205
    Assert should therefore only be used as a debugging tool
206
    and not used for authentication verification (e.g., verifying passwords),
207
    nor should side effects needed for the function to work correctly
208
    be used inside of asserts.
209

210
# Examples
211
```jldoctest
212
julia> @assert iseven(3) "3 is an odd number!"
213
ERROR: AssertionError: 3 is an odd number!
214

215
julia> @assert isodd(3) "What even are numbers?"
216
```
217
"""
218
macro assert(ex, msgs...)
1,134✔
219
    msg = isempty(msgs) ? ex : msgs[1]
1,144✔
220
    if isa(msg, AbstractString)
1,134✔
221
        msg = msg # pass-through
7✔
222
    elseif !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
1,127✔
223
        # message is an expression needing evaluating
224
        msg = :(Main.Base.string($(esc(msg))))
3✔
225
    elseif isdefined(Main, :Base) && isdefined(Main.Base, :string) && applicable(Main.Base.string, msg)
1,124✔
226
        msg = Main.Base.string(msg)
1,124✔
227
    else
228
        # string() might not be defined during bootstrap
229
        msg = quote
×
230
            msg = $(Expr(:quote,msg))
×
231
            isdefined(Main, :Base) ? Main.Base.string(msg) :
×
232
                (Core.println(msg); "Error during bootstrap. See stdout.")
×
233
        end
234
    end
235
    return :($(esc(ex)) ? $(nothing) : throw(AssertionError($msg)))
1,134✔
236
end
237

238
struct ExponentialBackOff
239
    n::Int
240
    first_delay::Float64
241
    max_delay::Float64
242
    factor::Float64
243
    jitter::Float64
244

245
    function ExponentialBackOff(n, first_delay, max_delay, factor, jitter)
17✔
246
        all(x->x>=0, (n, first_delay, max_delay, factor, jitter)) || error("all inputs must be non-negative")
102✔
247
        new(n, first_delay, max_delay, factor, jitter)
17✔
248
    end
249
end
250

251
"""
252
    ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1)
253

254
A [`Float64`](@ref) iterator of length `n` whose elements exponentially increase at a
255
rate in the interval `factor` * (1 ± `jitter`).  The first element is
256
`first_delay` and all elements are clamped to `max_delay`.
257
"""
258
ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1) =
34✔
259
    ExponentialBackOff(n, first_delay, max_delay, factor, jitter)
260
function iterate(ebo::ExponentialBackOff, state= (ebo.n, min(ebo.first_delay, ebo.max_delay)))
169✔
261
    state[1] < 1 && return nothing
185✔
262
    next_n = state[1]-1
143✔
263
    curr_delay = state[2]
143✔
264
    next_delay = min(ebo.max_delay, state[2] * ebo.factor * (1.0 - ebo.jitter + (Libc.rand(Float64) * 2.0 * ebo.jitter)))
143✔
265
    (curr_delay, (next_n, next_delay))
143✔
266
end
267
length(ebo::ExponentialBackOff) = ebo.n
4✔
268
eltype(::Type{ExponentialBackOff}) = Float64
3✔
269

270
"""
271
    retry(f;  delays=ExponentialBackOff(), check=nothing) -> Function
272

273
Return an anonymous function that calls function `f`.  If an exception arises,
274
`f` is repeatedly called again, each time `check` returns `true`, after waiting the
275
number of seconds specified in `delays`.  `check` should input `delays`'s
276
current state and the `Exception`.
277

278
!!! compat "Julia 1.2"
279
    Before Julia 1.2 this signature was restricted to `f::Function`.
280

281
# Examples
282
```julia
283
retry(f, delays=fill(5.0, 3))
284
retry(f, delays=rand(5:10, 2))
285
retry(f, delays=Base.ExponentialBackOff(n=3, first_delay=5, max_delay=1000))
286
retry(http_get, check=(s,e)->e.status == "503")(url)
287
retry(read, check=(s,e)->isa(e, IOError))(io, 128; all=false)
288
```
289
"""
290
function retry(f;  delays=ExponentialBackOff(), check=nothing)
79✔
291
    (args...; kwargs...) -> begin
2,807✔
292
        y = iterate(delays)
1,390✔
293
        while y !== nothing
1,403✔
294
            (delay, state) = y
1,374✔
295
            try
1,397✔
296
                return f(args...; kwargs...)
1,397✔
297
            catch e
298
                if check !== nothing
27✔
299
                    result = check(state, e)
16✔
300
                    state, retry_or_not = length(result) == 2 ? result : (state, result)
17✔
301
                    retry_or_not || rethrow()
29✔
302
                end
303
            end
304
            sleep(delay)
25✔
305
            y = iterate(delays, state)
26✔
306
        end
25✔
307
        # When delays is out, just run the function without try/catch
308
        return f(args...; kwargs...)
6✔
309
    end
310
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc