diff --git a/base/libuv.jl b/base/libuv.jl index b0116cd613d7e..77eadd73ce60e 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -59,8 +59,10 @@ type UVError <: Exception UVError(p::AbstractString,code::Integer)=new(p,code) end -struverror(err::UVError) = bytestring(ccall(:uv_strerror,Cstring,(Int32,),err.code)) -uverrorname(err::UVError) = bytestring(ccall(:uv_err_name,Cstring,(Int32,),err.code)) +struverror(err::Int32) = bytestring(ccall(:uv_strerror,Cstring,(Int32,),err)) +struverror(err::UVError) = struverror(err.code) +uverrorname(err::Int32) = bytestring(ccall(:uv_err_name,Cstring,(Int32,),err)) +uverrorname(err::UVError) = uverrorname(err.code) uv_error(prefix::Symbol, c::Integer) = uv_error(string(prefix),c) uv_error(prefix::AbstractString, c::Integer) = c < 0 ? throw(UVError(prefix,c)) : nothing diff --git a/base/socket.jl b/base/socket.jl index 367a5e149c321..436ff70fd4137 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -545,6 +545,16 @@ end ## +type DNSError <: Exception + host::AbstractString + code::Int32 +end + +function show(io::IO, err::DNSError) + print(io, "DNSError: ", err.host, ", ", struverror(err.code), + " (", uverrorname(err.code), ")") +end + callback_dict = ObjectIdDict() function uv_getaddrinfocb(req::Ptr{Void}, status::Cint, addrinfo::Ptr{Void}) @@ -553,7 +563,7 @@ function uv_getaddrinfocb(req::Ptr{Void}, status::Cint, addrinfo::Ptr{Void}) cb = unsafe_pointer_to_objref(data)::Function pop!(callback_dict,cb) # using pop forces an error if cb not in callback_dict if status != 0 || addrinfo == C_NULL - cb(UVError("getaddrinfo callback",status)) + cb(UVError("uv_getaddrinfocb received an unexpected status code", status)) else freeaddrinfo = addrinfo while addrinfo != C_NULL @@ -577,8 +587,16 @@ end function getaddrinfo(cb::Function, host::ASCIIString) callback_dict[cb] = cb - uv_error("getaddrinfo",ccall(:jl_getaddrinfo, Int32, (Ptr{Void}, Cstring, Ptr{UInt8}, Any, Ptr{Void}), - eventloop(), host, C_NULL, cb, uv_jl_getaddrinfocb::Ptr{Void})) + status = ccall(:jl_getaddrinfo, Int32, (Ptr{Void}, Cstring, Ptr{UInt8}, Any, Ptr{Void}), + eventloop(), host, C_NULL, cb, uv_jl_getaddrinfocb::Ptr{Void}) + if status == UV_EINVAL + throw(ArgumentError("Invalid uv_getaddrinfo() agument")) + elseif status in [UV_ENOMEM, UV_ENOBUFS] + throw(OutOfMemoryError()) + elseif status < 0 + throw(UVError("uv_getaddrinfo returned an unexpected error code", status)) + end + return nothing end getaddrinfo(cb::Function, host::AbstractString) = getaddrinfo(cb,ascii(host)) @@ -587,9 +605,19 @@ function getaddrinfo(host::ASCIIString) getaddrinfo(host) do IP notify(c,IP) end - ip = wait(c) - isa(ip,UVError) && throw(ip) - return ip::IPAddr + r = wait(c) + if isa(r,UVError) + if r.code in [UV_EAI_NONAME, UV_EAI_AGAIN, UV_EAI_FAIL, UV_EAI_NODATA] + throw(DNSError(host,r.code)) + elseif r.code == UV_EAI_SYSTEM + throw(SystemError("uv_getaddrinfocb")) + elseif r.code == UV_EAI_MEMORY + throw(OutOfMemoryError()) + else + throw(r) + end + end + return r::IPAddr end getaddrinfo(host::AbstractString) = getaddrinfo(ascii(host)) diff --git a/test/socket.jl b/test/socket.jl index 550fc65b73d5f..b9cba7b7e0750 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -107,7 +107,7 @@ mktempdir() do tmpdir end end -@test_throws Base.UVError getaddrinfo(".invalid") +@test_throws Base.DNSError getaddrinfo(".invalid") @test_throws ArgumentError getaddrinfo("localhost\0") # issue #10994 @test_throws Base.UVError connect("localhost", 21452) @@ -137,7 +137,7 @@ port2, server2 = listenany(port) close(server) close(server2) -@test_throws Base.UVError connect(".invalid",80) +@test_throws Base.DNSError connect(".invalid",80) begin a = UDPSocket()