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

JuliaLang / julia / #37474

pending completion
#37474

push

local

web-flow
irinterp: Allow setting all IR flags (#48993)

Currently, `IR_FLAG_NOTHROW` is the only flag that irinterp is allowed to
set on statements, under the assumption that in order for a call to
be irinterp-eligible, it must have been proven `:foldable`, thus `:effect_free`,
and thus `IR_FLAG_EFFECT_FREE` was assumed to have been set. That reasoning
was sound at the time this code was written, but have since introduced
`EFFECT_FREE_IF_INACCESSIBLEMEMONLY`, which breaks the reasoning that
an `:effect_free` inference for the whole function implies the flag on
every statement. As a result, we were failing to DCE otherwise dead
statements if the IR came from irinterp.

3 of 3 new or added lines in 1 file covered. (100.0%)

70258 of 82316 relevant lines covered (85.35%)

32461773.51 hits per line

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

75.76
/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
11
    host::String
3✔
12
    code::Int32
13
end
14

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

20
function uv_getaddrinfocb(req::Ptr{Cvoid}, status::Cint, addrinfo::Ptr{Cvoid})
8✔
21
    data = uv_req_data(req)
8✔
22
    if data != C_NULL
8✔
23
        t = unsafe_pointer_to_objref(data)::Task
8✔
24
        uv_req_set_data(req, C_NULL)
8✔
25
        if status != 0 || addrinfo == C_NULL
13✔
26
            schedule(t, _UVError("getaddrinfo", status))
3✔
27
        else
28
            freeaddrinfo = addrinfo
5✔
29
            addrs = IPAddr[]
5✔
30
            while addrinfo != C_NULL
13✔
31
                sockaddr = ccall(:jl_sockaddr_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo)
8✔
32
                if ccall(:jl_sockaddr_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1
8✔
33
                    ip4addr = ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr)
4✔
34
                    push!(addrs, IPv4(ntoh(ip4addr)))
4✔
35
                elseif ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1
4✔
36
                    ip6addr = Ref{UInt128}()
4✔
37
                    scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ptr{UInt128}), sockaddr, ip6addr)
4✔
38
                    push!(addrs, IPv6(ntoh(ip6addr[])))
4✔
39
                end
40
                addrinfo = ccall(:jl_next_from_addrinfo, Ptr{Cvoid}, (Ptr{Cvoid},), addrinfo)
8✔
41
            end
8✔
42
            ccall(:uv_freeaddrinfo, Cvoid, (Ptr{Cvoid},), freeaddrinfo)
5✔
43
            schedule(t, addrs)
13✔
44
        end
45
    else
46
        # no owner for this req, safe to just free it
47
        Libc.free(req)
×
48
    end
49
    nothing
8✔
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
# Example
59
```julia-repl
60
julia> getalladdrinfo("google.com")
61
2-element Array{IPAddr,1}:
62
 ip"172.217.6.174"
63
 ip"2607:f8b0:4000:804::200e"
64
```
65
"""
66
function getalladdrinfo(host::String)
9✔
67
    req = Libc.malloc(Base._sizeof_uv_getaddrinfo)
9✔
68
    uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call
9✔
69
    iolock_begin()
9✔
70
    status = ccall(:jl_getaddrinfo, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Ptr{Cvoid}),
9✔
71
                   eventloop(), req, host, #=service=#C_NULL,
72
                   @cfunction(uv_getaddrinfocb, Cvoid, (Ptr{Cvoid}, Cint, Ptr{Cvoid})))
73
    if status < 0
8✔
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
82
    ct = current_task()
8✔
83
    preserve_handle(ct)
8✔
84
    Base.sigatomic_begin()
8✔
85
    uv_req_set_data(req, ct)
8✔
86
    iolock_end()
8✔
87
    r = try
8✔
88
        Base.sigatomic_end()
8✔
89
        wait()
8✔
90
    finally
91
        Base.sigatomic_end()
8✔
92
        iolock_begin()
8✔
93
        ct.queue === nothing || list_deletefirst!(ct.queue, ct)
8✔
94
        if uv_req_data(req) != C_NULL
8✔
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
101
            Libc.free(req)
8✔
102
        end
103
        iolock_end()
8✔
104
        unpreserve_handle(ct)
8✔
105
    end
106
    if isa(r, IOError)
8✔
107
        code = r.code
3✔
108
        if code in (UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS,
3✔
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)
113
            throw(DNSError(host, code))
3✔
114
        elseif code == UV_EAI_MEMORY
×
115
            throw(OutOfMemoryError())
×
116
        else
117
            throw(r)
×
118
        end
119
    end
120
    return r::Vector{IPAddr}
5✔
121
end
122
getalladdrinfo(host::AbstractString) = getalladdrinfo(String(host))
×
123

124
"""
125
    getaddrinfo(host::AbstractString, IPAddr=IPv4) -> 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 a DNS lookup.
129
"""
130
function getaddrinfo(host::String, T::Type{<:IPAddr})
2✔
131
    addrs = getalladdrinfo(host)
2✔
132
    for addr in addrs
2✔
133
        if addr isa T
3✔
134
            return addr
2✔
135
        end
136
    end
1✔
137
    throw(DNSError(host, UV_EAI_NONAME))
×
138
end
139
getaddrinfo(host::AbstractString, T::Type{<:IPAddr}) = getaddrinfo(String(host), T)
×
140
function getaddrinfo(host::AbstractString)
6✔
141
    addrs = getalladdrinfo(String(host))
6✔
142
    if !isempty(addrs)
2✔
143
        return addrs[begin]::Union{IPv4,IPv6}
2✔
144
    end
145
    throw(DNSError(host, UV_EAI_NONAME))
×
146
end
147

148
function uv_getnameinfocb(req::Ptr{Cvoid}, status::Cint, hostname::Cstring, service::Cstring)
24✔
149
    data = uv_req_data(req)
24✔
150
    if data != C_NULL
24✔
151
        t = unsafe_pointer_to_objref(data)::Task
24✔
152
        uv_req_set_data(req, C_NULL)
24✔
153
        if status != 0
24✔
154
            schedule(t, _UVError("getnameinfo", status))
×
155
        else
156
            schedule(t, unsafe_string(hostname))
48✔
157
        end
158
    else
159
        # no owner for this req, safe to just free it
160
        Libc.free(req)
×
161
    end
162
    nothing
24✔
163
end
164

165
"""
166
    getnameinfo(host::IPAddr) -> String
167

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

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

238
const _sizeof_uv_interface_address = ccall(:jl_uv_sizeof_interface_address,Int32,())
239

240
"""
241
    getipaddr() -> IPAddr
242

243
Get an IP address of the local machine, preferring IPv4 over IPv6. Throws if no
244
addresses are available.
245

246
    getipaddr(addr_type::Type{T}) where T<:IPAddr -> T
247

248
Get an IP address of the local machine of the specified type. Throws if no
249
addresses of the specified type are available.
250

251
This function is a backwards-compatibility wrapper around [`getipaddrs`](@ref).
252
New applications should use [`getipaddrs`](@ref) instead.
253

254
# Examples
255
```julia-repl
256
julia> getipaddr()
257
ip"192.168.1.28"
258

259
julia> getipaddr(IPv6)
260
ip"fe80::9731:35af:e1c5:6e49"
261
```
262

263
See also [`getipaddrs`](@ref).
264
"""
265
function getipaddr(addr_type::Type{T}) where T<:IPAddr
18✔
266
    addrs = getipaddrs(addr_type)
18✔
267

268
    if length(addrs) == 0
18✔
269
        error("No networking interface available")
×
270
    end
271

272
    # Prefer the first IPv4 address
273
    i = something(findfirst(ip -> ip isa IPv4, addrs), 1)
54✔
274
    return addrs[i]
18✔
275
end
276
getipaddr() = getipaddr(IPv4)
34✔
277

278

279
"""
280
    getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IPAddr -> Vector{T}
281

282
Get the IP addresses of the local machine.
283

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

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

288
!!! compat "Julia 1.2"
289
    This function is available as of Julia 1.2.
290

291
# Examples
292
```julia-repl
293
julia> getipaddrs()
294
5-element Array{IPAddr,1}:
295
 ip"198.51.100.17"
296
 ip"203.0.113.2"
297
 ip"2001:db8:8:4:445e:5fff:fe5d:5500"
298
 ip"2001:db8:8:4:c164:402e:7e3c:3668"
299
 ip"fe80::445e:5fff:fe5d:5500"
300

301
julia> getipaddrs(IPv6)
302
3-element Array{IPv6,1}:
303
 ip"2001:db8:8:4:445e:5fff:fe5d:5500"
304
 ip"2001:db8:8:4:c164:402e:7e3c:3668"
305
 ip"fe80::445e:5fff:fe5d:5500"
306
```
307

308
See also [`islinklocaladdr`](@ref).
309
"""
310
function getipaddrs(addr_type::Type{T}=IPAddr; loopback::Bool=false) where T<:IPAddr
36✔
311
    addresses = T[]
18✔
312
    addr_ref = Ref{Ptr{UInt8}}(C_NULL)
18✔
313
    count_ref = Ref{Int32}(1)
18✔
314
    lo_present = false
18✔
315
    err = ccall(:jl_uv_interface_addresses, Int32, (Ref{Ptr{UInt8}}, Ref{Int32}), addr_ref, count_ref)
18✔
316
    uv_error("getlocalip", err)
18✔
317
    addr, count = addr_ref[], count_ref[]
18✔
318
    for i = 0:(count-1)
36✔
319
        current_addr = addr + i*_sizeof_uv_interface_address
90✔
320
        if 1 == ccall(:jl_uv_interface_address_is_internal, Int32, (Ptr{UInt8},), current_addr)
90✔
321
            lo_present = true
36✔
322
            if !loopback
36✔
323
                continue
36✔
324
            end
325
        end
326
        sockaddr = ccall(:jl_uv_interface_address_sockaddr, Ptr{Cvoid}, (Ptr{UInt8},), current_addr)
54✔
327
        if IPv4 <: T && ccall(:jl_sockaddr_is_ip4, Int32, (Ptr{Cvoid},), sockaddr) == 1
54✔
328
            push!(addresses, IPv4(ntoh(ccall(:jl_sockaddr_host4, UInt32, (Ptr{Cvoid},), sockaddr))))
18✔
329
        elseif IPv6 <: T && ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Cvoid},), sockaddr) == 1
36✔
330
            addr6 = Ref{UInt128}()
×
331
            scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Cvoid}, Ref{UInt128},), sockaddr, addr6)
×
332
            push!(addresses, IPv6(ntoh(addr6[])))
×
333
        end
334
    end
162✔
335
    ccall(:uv_free_interface_addresses, Cvoid, (Ptr{UInt8}, Int32), addr, count)
18✔
336
    return addresses
18✔
337
end
338

339
"""
340
    islinklocaladdr(addr::IPAddr)
341

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

347
# Example
348
```julia
349
filter(!islinklocaladdr, getipaddrs())
350
```
351
"""
352
function islinklocaladdr(addr::IPv4)
×
353
    # RFC 3927
354
    return (addr.host &
×
355
            0xFFFF0000) ==
356
            0xA9FE0000
357
end
358
function islinklocaladdr(addr::IPv6)
×
359
    # RFC 4291
360
    return (addr.host &
×
361
            0xFFC00000000000000000000000000000) ==
362
            0xFE800000000000000000000000000000
363
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