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

JuliaLang / julia / #38162

06 Aug 2025 08:25PM UTC coverage: 25.688% (-43.6%) from 69.336%
#38162

push

local

web-flow
fix runtime cglobal builtin function implementation (#59210)

This had failed to be updated for the LazyLibrary changes to codegen.

12976 of 50513 relevant lines covered (25.69%)

676965.51 hits per line

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

54.64
/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
# This is `Experimental.@max_methods 2 function error end`, which is not available at this point in bootstrap.
31
# NOTE It is important to always be able to infer the return type of `error` as `Union{}`,
32
# but there's a hitch when a package globally sets `@max_methods 1` and it causes inference
33
# for `error(::Any)` to fail (JuliaLang/julia#54029).
34
# This definition site `@max_methods 2` setting overrides any global `@max_methods 1` settings
35
# on package side, guaranteeing that return type inference on `error` is successful always.
36
function error end
37
typeof(error).name.max_methods = UInt8(2)
38

39
"""
40
    error(message::AbstractString)
41

42
Raise an `ErrorException` with the given message.
43
"""
44
error(s::AbstractString) = throw(ErrorException(s))
1✔
45
error() = throw(ErrorException(""))
×
46

47
"""
48
    error(msg...)
49

50
Raise an `ErrorException` with a message constructed by `string(msg...)`.
51
"""
52
function error(s::Vararg{Any,N}) where {N}
×
53
    @noinline
×
54
    throw(ErrorException(Main.Base.string(s...)))
×
55
end
56

57
"""
58
    rethrow()
59

60
Rethrow the current exception from within a `catch` block. The rethrown
61
exception will continue propagation as if it had not been caught.
62

63
!!! note
64
    The alternative form `rethrow(e)` allows you to associate an alternative
65
    exception object `e` with the current backtrace. However this misrepresents
66
    the program state at the time of the error so you're encouraged to instead
67
    throw a new exception using `throw(e)`. In Julia 1.1 and above, using
68
    `throw(e)` will preserve the root cause exception on the stack, as
69
    described in [`current_exceptions`](@ref).
70
"""
71
rethrow() = ccall(:jl_rethrow, Bottom, ())
22✔
72
rethrow(@nospecialize(e)) = ccall(:jl_rethrow_other, Bottom, (Any,), e)
17✔
73

74
struct InterpreterIP
75
    code::Union{CodeInfo,Core.MethodInstance,Core.CodeInstance,Nothing}
3✔
76
    stmt::Csize_t
77
    mod::Union{Module,Nothing}
78
end
79

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

114
"""
115
    backtrace()
116

117
Get a backtrace object for the current program point.
118
"""
119
function backtrace()
×
120
    @noinline
×
121
    # skip frame for backtrace(). Note that for this to work properly,
122
    # backtrace() itself must not be interpreted nor inlined.
123
    skip = 1
×
124
    bt1, bt2 = ccall(:jl_backtrace_from_here, Ref{SimpleVector}, (Cint, Cint), false, skip)
×
125
    return _reformat_bt(bt1::Vector{Ptr{Cvoid}}, bt2::Vector{Any})
×
126
end
127

128
"""
129
    catch_backtrace()
130

131
Get the backtrace of the current exception, for use within `catch` blocks.
132
"""
133
function catch_backtrace()
×
134
    bt, bt2 = ccall(:jl_get_backtrace, Ref{SimpleVector}, ())
×
135
    return _reformat_bt(bt::Vector{Ptr{Cvoid}}, bt2::Vector{Any})
×
136
end
137

138
struct ExceptionStack <: AbstractArray{NamedTuple{(:exception, :backtrace)},1}
139
    stack::Array{NamedTuple{(:exception, :backtrace)},1}
5✔
140
end
141

142
"""
143
    current_exceptions(task::Task=current_task(); [backtrace::Bool=true])
144

145
Get the stack of exceptions currently being handled. For nested catch blocks
146
there may be more than one current exception in which case the most recently
147
thrown exception is last in the stack. The stack is returned as an
148
`ExceptionStack` which is an AbstractVector of named tuples
149
`(exception,backtrace)`. If `backtrace` is false, the backtrace in each pair
150
will be set to `nothing`.
151

152
Explicitly passing `task` will return the current exception stack on an
153
arbitrary task. This is useful for inspecting tasks which have failed due to
154
uncaught exceptions.
155

156
!!! compat "Julia 1.7"
157
    This function went by the experimental name `catch_stack()` in Julia
158
    1.1–1.6, and had a plain Vector-of-tuples as a return type.
159
"""
160
function current_exceptions(task::Task=current_task(); backtrace::Bool=true)
12✔
161
    raw = ccall(:jl_get_excstack, Any, (Any,Cint,Cint), task, backtrace, typemax(Cint))::Vector{Any}
3✔
162
    formatted = NamedTuple{(:exception, :backtrace)}[]
3✔
163
    stride = backtrace ? 3 : 1
3✔
164
    for i = reverse(1:stride:length(raw))
5✔
165
        exc = raw[i]
5✔
166
        bt = backtrace ? Base._reformat_bt(raw[i+1],raw[i+2]) : nothing
5✔
167
        push!(formatted, (exception=exc,backtrace=bt))
5✔
168
    end
7✔
169
    ExceptionStack(formatted)
3✔
170
end
171

172
## keyword arg lowering generates calls to this ##
173
function kwerr(kw, args::Vararg{Any,N}) where {N}
×
174
    @noinline
×
175
    throw(MethodError(Core.kwcall, (kw, args...), tls_world_age()))
×
176
end
177

178
## system error handling ##
179
"""
180
    systemerror(sysfunc[, errno::Cint=Libc.errno()])
181
    systemerror(sysfunc, iftrue::Bool)
182

183
Raises a `SystemError` for `errno` with the descriptive string `sysfunc` if `iftrue` is `true`
184
"""
185
systemerror(p, b::Bool; extrainfo=nothing) = b ? systemerror(p, extrainfo=extrainfo) : nothing
2,896✔
186
systemerror(p, errno::Cint=Libc.errno(); extrainfo=nothing) = throw(Main.Base.SystemError(string(p), errno, extrainfo))
×
187

188
## system errors from Windows API functions
189
struct WindowsErrorInfo
190
    errnum::UInt32
191
    extrainfo
192
end
193
"""
194
    windowserror(sysfunc[, code::UInt32=Libc.GetLastError()])
195
    windowserror(sysfunc, iftrue::Bool)
196

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

203

204
## assertion macro ##
205

206

207
"""
208
    @assert cond [text]
209

210
Throw an [`AssertionError`](@ref) if `cond` is `false`. This is the preferred syntax for
211
writing assertions, which are conditions that are assumed to be true, but that the user
212
might decide to check anyways, as an aid to debugging if they fail.
213
The optional message `text` is displayed upon assertion failure.
214

215
!!! warning
216
    An assert might be disabled at some optimization levels.
217
    Assert should therefore only be used as a debugging tool
218
    and not used for authentication verification (e.g., verifying passwords or checking array bounds).
219
    The code must not rely on the side effects of running `cond` for the correct behavior
220
    of a function.
221

222
# Examples
223
```jldoctest
224
julia> @assert iseven(3) "3 is an odd number!"
225
ERROR: AssertionError: 3 is an odd number!
226

227
julia> @assert isodd(3) "What even are numbers?"
228
```
229
"""
230
macro assert(ex, msgs...)
80✔
231
    msg = isempty(msgs) ? ex : msgs[1]
159✔
232
    if isa(msg, AbstractString)
80✔
233
        msg = msg # pass-through
79✔
234
    elseif !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
1✔
235
        # message is an expression needing evaluating
236
        # N.B. To reduce the risk of invalidation caused by the complex callstack involved
237
        # with `string`, use `inferencebarrier` here to hide this `string` from the compiler.
238
        msg = :(Main.Base.inferencebarrier(Main.Base.string)($(esc(msg))))
×
239
    elseif isdefined(Main, :Base) && isdefined(Main.Base, :string) && applicable(Main.Base.string, msg)
1✔
240
        msg = Main.Base.string(msg)
1✔
241
    else
242
        # string() might not be defined during bootstrap
243
        msg = :(_assert_tostring($(Expr(:quote,msg))))
×
244
    end
245
    return :($(esc(ex)) ? $(nothing) : throw(AssertionError($msg)))
80✔
246
end
247

248
# this may be overridden in contexts where `string(::Expr)` doesn't work
249
_assert_tostring(@nospecialize(msg)) = Core.compilerbarrier(:type, __assert_tostring)(msg)
×
250
__assert_tostring(msg) = isdefined(Main, :Base) ? Main.Base.string(msg) :
×
251
    (Core.println(msg); "Error during bootstrap. See stdout.")
×
252

253
struct ExponentialBackOff
254
    n::Int
255
    first_delay::Float64
256
    max_delay::Float64
257
    factor::Float64
258
    jitter::Float64
259

260
    function ExponentialBackOff(n, first_delay, max_delay, factor, jitter)
×
261
        all(x->x>=0, (n, first_delay, max_delay, factor, jitter)) || error("all inputs must be non-negative")
×
262
        new(n, first_delay, max_delay, factor, jitter)
×
263
    end
264
end
265

266
"""
267
    ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1)
268

269
A [`Float64`](@ref) iterator of length `n` whose elements exponentially increase at a
270
rate in the interval `factor` * (1 ± `jitter`).  The first element is
271
`first_delay` and all elements are clamped to `max_delay`.
272
"""
273
ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1) =
×
274
    ExponentialBackOff(n, first_delay, max_delay, factor, jitter)
275
function iterate(ebo::ExponentialBackOff, state= (ebo.n, min(ebo.first_delay, ebo.max_delay)))
×
276
    state[1] < 1 && return nothing
×
277
    next_n = state[1]-1
×
278
    curr_delay = state[2]
×
279
    next_delay = min(ebo.max_delay, state[2] * ebo.factor * (1.0 - ebo.jitter + (Libc.rand(Float64) * 2.0 * ebo.jitter)))
×
280
    (curr_delay, (next_n, next_delay))
×
281
end
282
length(ebo::ExponentialBackOff) = ebo.n
×
283
eltype(::Type{ExponentialBackOff}) = Float64
×
284

285
"""
286
    retry(f;  delays=ExponentialBackOff(), check=nothing) -> Function
287

288
Return an anonymous function that calls function `f`.  If an exception arises,
289
`f` is repeatedly called again, each time `check` returns `true`, after waiting the
290
number of seconds specified in `delays`.  `check` should input `delays`'s
291
current state and the `Exception`.
292

293
!!! compat "Julia 1.2"
294
    Before Julia 1.2 this signature was restricted to `f::Function`.
295

296
# Examples
297
```julia
298
retry(f, delays=fill(5.0, 3))
299
retry(f, delays=rand(5:10, 2))
300
retry(f, delays=Base.ExponentialBackOff(n=3, first_delay=5, max_delay=1000))
301
retry(http_get, check=(s,e)->e.status == "503")(url)
302
retry(read, check=(s,e)->isa(e, IOError))(io, 128; all=false)
303
```
304
"""
305
function retry(f;  delays=ExponentialBackOff(), check=nothing)
5✔
306
    (args...; kwargs...) -> begin
15✔
307
        y = iterate(delays)
5✔
308
        while y !== nothing
5✔
309
            (delay, state) = y
5✔
310
            try
5✔
311
                return f(args...; kwargs...)
5✔
312
            catch e
313
                if check !== nothing
×
314
                    result = check(state, e)
×
315
                    state, retry_or_not = length(result) == 2 ? result : (state, result)
×
316
                    retry_or_not || rethrow()
×
317
                end
318
            end
319
            sleep(delay)
×
320
            y = iterate(delays, state)
×
321
        end
×
322
        # When delays is out, just run the function without try/catch
323
        return f(args...; kwargs...)
×
324
    end
325
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

© 2026 Coveralls, Inc