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

JuliaLang / julia / #37997

29 Jan 2025 02:08AM UTC coverage: 17.283% (-68.7%) from 85.981%
#37997

push

local

web-flow
bpart: Start enforcing min_world for global variable definitions (#57150)

This is the analog of #57102 for global variables. Unlike for consants,
there is no automatic global backdate mechanism. The reasoning for this
is that global variables can be declared at any time, unlike constants
which can only be decalared once their value is available. As a result
code patterns using `Core.eval` to declare globals are rarer and likely
incorrect.

1 of 22 new or added lines in 3 files covered. (4.55%)

31430 existing lines in 188 files now uncovered.

7903 of 45728 relevant lines covered (17.28%)

98663.7 hits per line

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

4.29
/stdlib/Sockets/src/addrinfo.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    DNSError
5

6
The type of exception thrown when an error occurs in DNS lookup.
7
The `host` field indicates the host URL string.
8
The `code` field indicates the error code based on libuv.
9
"""
10
struct DNSError <: Exception
UNCOV
11
    host::String
×
12
    code::Int32
13
end
14

UNCOV
15
function show(io::IO, err::DNSError)
×
UNCOV
16
    print(io, "DNSError: ", err.host, ", ", Base.struverror(err.code),
×
17
                                      " (", Base.uverrorname(err.code), ")")
18
end
19

UNCOV
20
function uv_getaddrinfocb(req::Ptr{Cvoid}, status::Cint, addrinfo::Ptr{Cvoid})
×
UNCOV
21
    data = uv_req_data(req)
×
UNCOV
22
    if data != C_NULL
×
UNCOV
23
        t = unsafe_pointer_to_objref(data)::Task
×
UNCOV
24
        uv_req_set_data(req, C_NULL)
×
UNCOV
25
        if status != 0 || addrinfo == C_NULL
×
UNCOV
26
            schedule(t, _UVError("getaddrinfo", status))
×
27
        else
UNCOV
28
            freeaddrinfo = addrinfo
×
UNCOV
29
            addrs = IPAddr[]
×
UNCOV
30
            while addrinfo != C_NULL
×
UNCOV
31
                sockaddr = ccall(:jl_sockaddr_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo)
×
UNCOV
32
                if ccall(:jl_sockaddr_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1
×
UNCOV
33
                    ip4addr = ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr)
×
UNCOV
34
                    push!(addrs, IPv4(ntoh(ip4addr)))
×
UNCOV
35
                elseif ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1
×
UNCOV
36
                    ip6addr = Ref{UInt128}()
×
UNCOV
37
                    scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ptr{UInt128}), sockaddr, ip6addr)
×
UNCOV
38
                    push!(addrs, IPv6(ntoh(ip6addr[])))
×
39
                end
UNCOV
40
                addrinfo = ccall(:jl_next_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo)
×
UNCOV
41
            end
×
UNCOV
42
            ccall(:uv_freeaddrinfo, Cvoid, (Ptr{Cvoid},), freeaddrinfo)
×
UNCOV
43
            schedule(t, addrs)
×
44
        end
45
    else
46
        # no owner for this req, safe to just free it
47
        Libc.free(req)
×
48
    end
UNCOV
49
    nothing
×
50
end
51

52
"""
53
    getalladdrinfo(host::AbstractString) -> Vector{IPAddr}
54

55
Gets all of the IP addresses of the `host`.
56
Uses the operating system's underlying `getaddrinfo` implementation, which may do a DNS lookup.
57

58
# Examples
59
```julia-repl
60
julia> getalladdrinfo("google.com")
61
2-element Vector{IPAddr}:
62
 ip"172.217.6.174"
63
 ip"2607:f8b0:4000:804::200e"
64
```
65
"""
UNCOV
66
function getalladdrinfo(host::String)
×
UNCOV
67
    req = Libc.malloc(Base._sizeof_uv_getaddrinfo)
×
UNCOV
68
    uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call
×
UNCOV
69
    iolock_begin()
×
UNCOV
70
    status = ccall(:jl_getaddrinfo, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Ptr{Cvoid}),
×
71
                   eventloop(), req, host, #=service=#C_NULL,
UNCOV
72
                   @cfunction(uv_getaddrinfocb, Cvoid, (Ptr{Cvoid}, Cint, Ptr{Cvoid})))
×
UNCOV
73
    if status < 0
×
74
        Libc.free(req)
×
75
        if status == UV_EINVAL
×
76
            throw(ArgumentError("Invalid getaddrinfo argument"))
×
77
        elseif status == UV_ENOMEM || status == UV_ENOBUFS
×
78
            throw(OutOfMemoryError())
×
79
        end
80
        uv_error("getaddrinfo", status)
×
81
    end
UNCOV
82
    ct = current_task()
×
UNCOV
83
    preserve_handle(ct)
×
UNCOV
84
    Base.sigatomic_begin()
×
UNCOV
85
    uv_req_set_data(req, ct)
×
UNCOV
86
    iolock_end()
×
UNCOV
87
    r = try
×
UNCOV
88
        Base.sigatomic_end()
×
UNCOV
89
        wait()
×
90
    finally
UNCOV
91
        Base.sigatomic_end()
×
UNCOV
92
        iolock_begin()
×
UNCOV
93
        q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct)
×
UNCOV
94
        if uv_req_data(req) != C_NULL
×
95
            # req is still alive,
96
            # so make sure we don't get spurious notifications later
97
            uv_req_set_data(req, C_NULL)
×
98
            ccall(:uv_cancel, Int32, (Ptr{Cvoid},), req) # try to let libuv know we don't care anymore
×
99
        else
100
            # done with req
UNCOV
101
            Libc.free(req)
×
102
        end
UNCOV
103
        iolock_end()
×
UNCOV
104
        unpreserve_handle(ct)
×
105
    end
UNCOV
106
    if isa(r, IOError)
×
UNCOV
107
        code = r.code
×
UNCOV
108
        if code in (UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS,
×
109
                    UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL,
110
                    UV_EAI_FAMILY, UV_EAI_NODATA, UV_EAI_NONAME,
111
                    UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE,
112
                    UV_EAI_SOCKTYPE)
UNCOV
113
            throw(DNSError(host, code))
×
114
        elseif code == UV_EAI_MEMORY
×
115
            throw(OutOfMemoryError())
×
116
        else
117
            throw(r)
×
118
        end
119
    end
UNCOV
120
    return r::Vector{IPAddr}
×
121
end
122
getalladdrinfo(host::AbstractString) = getalladdrinfo(String(host))
×
123

124
"""
125
    getaddrinfo(host::AbstractString, IPAddr) -> IPAddr
126

127
Gets the first IP address of the `host` of the specified `IPAddr` type.
128
Uses the operating system's underlying getaddrinfo implementation, which may do
129
a DNS lookup.
130

131
# Examples
132
```julia-repl
133
julia> getaddrinfo("localhost", IPv6)
134
ip"::1"
135

136
julia> getaddrinfo("localhost", IPv4)
137
ip"127.0.0.1"
138
```
139
"""
UNCOV
140
function getaddrinfo(host::String, T::Type{<:IPAddr})
×
UNCOV
141
    addrs = getalladdrinfo(host)
×
UNCOV
142
    for addr in addrs
×
UNCOV
143
        if addr isa T
×
UNCOV
144
            return addr
×
145
        end
UNCOV
146
    end
×
147
    throw(DNSError(host, UV_EAI_NONAME))
×
148
end
149
getaddrinfo(host::AbstractString, T::Type{<:IPAddr}) = getaddrinfo(String(host), T)
×
150

151
"""
152
    getaddrinfo(host::AbstractString) -> IPAddr
153

154
Gets the first available IP address of `host`, which may be either an `IPv4` or
155
`IPv6` address. Uses the operating system's underlying getaddrinfo
156
implementation, which may do a DNS lookup.
157
"""
158
function getaddrinfo(host::AbstractString)
UNCOV
159
    addrs = getalladdrinfo(String(host))
×
UNCOV
160
    if !isempty(addrs)
×
UNCOV
161
        return addrs[begin]::Union{IPv4,IPv6}
×
162
    end
163
    throw(DNSError(host, UV_EAI_NONAME))
×
164
end
165

UNCOV
166
function uv_getnameinfocb(req::Ptr{Cvoid}, status::Cint, hostname::Cstring, service::Cstring)
×
UNCOV
167
    data = uv_req_data(req)
×
UNCOV
168
    if data != C_NULL
×
UNCOV
169
        t = unsafe_pointer_to_objref(data)::Task
×
UNCOV
170
        uv_req_set_data(req, C_NULL)
×
UNCOV
171
        if status != 0
×
172
            schedule(t, _UVError("getnameinfo", status))
×
173
        else
UNCOV
174
            schedule(t, unsafe_string(hostname))
×
175
        end
176
    else
177
        # no owner for this req, safe to just free it
178
        Libc.free(req)
×
179
    end
UNCOV
180
    nothing
×
181
end
182

183
"""
184
    getnameinfo(host::IPAddr) -> String
185

186
Performs a reverse-lookup for IP address to return a hostname and service
187
using the operating system's underlying `getnameinfo` implementation.
188

189
# Examples
190
```julia-repl
191
julia> getnameinfo(IPv4("8.8.8.8"))
192
"google-public-dns-a.google.com"
193
```
194
"""
UNCOV
195
function getnameinfo(address::Union{IPv4, IPv6})
×
UNCOV
196
    req = Libc.malloc(Base._sizeof_uv_getnameinfo)
×
UNCOV
197
    uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call
×
UNCOV
198
    port = hton(UInt16(0))
×
UNCOV
199
    flags = 0
×
UNCOV
200
    uvcb = @cfunction(uv_getnameinfocb, Cvoid, (Ptr{Cvoid}, Cint, Cstring, Cstring))
×
UNCOV
201
    status = UV_EINVAL
×
UNCOV
202
    host_in = Ref(hton(address.host))
×
UNCOV
203
    iolock_begin()
×
UNCOV
204
    status = ccall(:jl_getnameinfo, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, UInt16, Cint, Ptr{Cvoid}, Cint),
×
205
                   eventloop(), req, host_in, port, flags, uvcb, address isa IPv6)
UNCOV
206
    if status < 0
×
207
        Libc.free(req)
×
208
        if status == UV_EINVAL
×
209
            throw(ArgumentError("Invalid getnameinfo argument"))
×
210
        elseif status == UV_ENOMEM || status == UV_ENOBUFS
×
211
            throw(OutOfMemoryError())
×
212
        end
213
        uv_error("getnameinfo", status)
×
214
    end
UNCOV
215
    ct = current_task()
×
UNCOV
216
    preserve_handle(ct)
×
UNCOV
217
    Base.sigatomic_begin()
×
UNCOV
218
    uv_req_set_data(req, ct)
×
UNCOV
219
    iolock_end()
×
UNCOV
220
    r = try
×
UNCOV
221
        Base.sigatomic_end()
×
UNCOV
222
        wait()
×
223
    finally
UNCOV
224
        Base.sigatomic_end()
×
UNCOV
225
        iolock_begin()
×
UNCOV
226
        q = ct.queue; q === nothing || Base.list_deletefirst!(q::IntrusiveLinkedList{Task}, ct)
×
UNCOV
227
        if uv_req_data(req) != C_NULL
×
228
            # req is still alive,
229
            # so make sure we don't get spurious notifications later
230
            uv_req_set_data(req, C_NULL)
×
231
            ccall(:uv_cancel, Int32, (Ptr{Cvoid},), req) # try to let libuv know we don't care anymore
×
232
        else
233
            # done with req
UNCOV
234
            Libc.free(req)
×
235
        end
UNCOV
236
        iolock_end()
×
UNCOV
237
        unpreserve_handle(ct)
×
238
    end
UNCOV
239
    if isa(r, IOError)
×
240
        code = r.code
×
241
        if code in (UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS,
×
242
                    UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL,
243
                    UV_EAI_FAMILY, UV_EAI_NODATA, UV_EAI_NONAME,
244
                    UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE,
245
                    UV_EAI_SOCKTYPE)
246
            throw(DNSError(repr(address), code))
×
247
        elseif code == UV_EAI_MEMORY
×
248
            throw(OutOfMemoryError())
×
249
        else
250
            throw(r)
×
251
        end
252
    end
UNCOV
253
    return r::String
×
254
end
255

256
const _sizeof_uv_interface_address = ccall(:jl_uv_sizeof_interface_address,Int32,())
257

258
"""
259
    getipaddr() -> IPAddr
260

261
Get an IP address of the local machine, preferring IPv4 over IPv6. Throws if no
262
addresses are available.
263

264
    getipaddr(addr_type::Type{T}) where T<:IPAddr -> T
265

266
Get an IP address of the local machine of the specified type. Throws if no
267
addresses of the specified type are available.
268

269
This function is a backwards-compatibility wrapper around [`getipaddrs`](@ref).
270
New applications should use [`getipaddrs`](@ref) instead.
271

272
# Examples
273
```julia-repl
274
julia> getipaddr()
275
ip"192.168.1.28"
276

277
julia> getipaddr(IPv6)
278
ip"fe80::9731:35af:e1c5:6e49"
279
```
280

281
See also [`getipaddrs`](@ref).
282
"""
283
function getipaddr(addr_type::Type{T}) where T<:IPAddr
284
    addrs = getipaddrs(addr_type)
5✔
285
    isempty(addrs) && error("No networking interface available")
5✔
286

287
    # When `addr_type` is `IPAddr`, `addrs` contain IP addresses of all types
288
    # In that case, we prefer to return the first IPv4
289
    i = something(findfirst(ip -> ip isa IPv4, addrs), 1)
15✔
290
    return addrs[i]
5✔
291
end
292
getipaddr() = getipaddr(IPAddr)
5✔
293

294

295
"""
296
    getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IPAddr -> Vector{T}
297

298
Get the IP addresses of the local machine.
299

300
Setting the optional `addr_type` parameter to `IPv4` or `IPv6` causes only addresses of that type to be returned.
301

302
The `loopback` keyword argument dictates whether loopback addresses (e.g. `ip"127.0.0.1"`, `ip"::1"`) are included.
303

304
!!! compat "Julia 1.2"
305
    This function is available as of Julia 1.2.
306

307
# Examples
308
```julia-repl
309
julia> getipaddrs()
310
5-element Vector{IPAddr}:
311
 ip"198.51.100.17"
312
 ip"203.0.113.2"
313
 ip"2001:db8:8:4:445e:5fff:fe5d:5500"
314
 ip"2001:db8:8:4:c164:402e:7e3c:3668"
315
 ip"fe80::445e:5fff:fe5d:5500"
316

317
julia> getipaddrs(IPv6)
318
3-element Vector{IPv6}:
319
 ip"2001:db8:8:4:445e:5fff:fe5d:5500"
320
 ip"2001:db8:8:4:c164:402e:7e3c:3668"
321
 ip"fe80::445e:5fff:fe5d:5500"
322
```
323

324
See also [`islinklocaladdr`](@ref).
325
"""
326
function getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IPAddr
5✔
327
    addresses = T[]
328
    addr_ref = Ref{Ptr{UInt8}}(C_NULL)
329
    count_ref = Ref{Int32}(1)
330
    lo_present = false
331
    err = ccall(:jl_uv_interface_addresses, Int32, (Ref{Ptr{UInt8}}, Ref{Int32}), addr_ref, count_ref)
332
    uv_error("getlocalip", err)
333
    addr, count = addr_ref[], count_ref[]
334
    for i = 0:(count-1)
335
        current_addr = addr + i*_sizeof_uv_interface_address
336
        if 1 == ccall(:jl_uv_interface_address_is_internal, Int32, (Ptr{UInt8},), current_addr)
337
            lo_present = true
338
            if !loopback
339
                continue
340
            end
341
        end
342
        sockaddr = ccall(:jl_uv_interface_address_sockaddr, Ptr{Cvoid}, (Ptr{UInt8},), current_addr)
343
        if IPv4 <: T && ccall(:jl_sockaddr_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1
344
            push!(addresses, IPv4(ntoh(ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr))))
345
        elseif IPv6 <: T && ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1
346
            addr6 = Ref{UInt128}()
347
            scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ref{UInt128},), sockaddr, addr6)
348
            push!(addresses, IPv6(ntoh(addr6[])))
349
        end
350
    end
351
    ccall(:uv_free_interface_addresses, Cvoid, (Ptr{UInt8}, Int32), addr, count)
352
    return addresses
353
end
354

355
"""
356
    islinklocaladdr(addr::IPAddr)
357

358
Tests if an IP address is a link-local address. Link-local addresses
359
are not guaranteed to be unique beyond their network segment,
360
therefore routers do not forward them. Link-local addresses are from
361
the address blocks `169.254.0.0/16` or `fe80::/10`.
362

363
# Examples
364
```julia
365
filter(!islinklocaladdr, getipaddrs())
366
```
367
"""
UNCOV
368
function islinklocaladdr(addr::IPv4)
×
369
    # RFC 3927
UNCOV
370
    return (addr.host &
×
371
            0xFFFF0000) ==
372
            0xA9FE0000
373
end
UNCOV
374
function islinklocaladdr(addr::IPv6)
×
375
    # RFC 4291
UNCOV
376
    return (addr.host &
×
377
            0xFFC00000000000000000000000000000) ==
378
            0xFE800000000000000000000000000000
379
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