diff --git a/base/Makefile b/base/Makefile index 64cef54a83d41..cfc576913c50e 100644 --- a/base/Makefile +++ b/base/Makefile @@ -38,7 +38,7 @@ file_constants.jl: ../src/file_constants.h $(QUIET_PERL) ${CC} -E -P -DJULIA ../src/file_constants.h | perl -nle 'print "$$1 0o$$2" if /^(\s*const\s+[A-z_]+\s+=)\s+(0[0-9]*)\s*$$/; print "$$1" if /^\s*(const\s+[A-z_]+\s+=\s+([1-9]|0x)[0-9A-z]*)\s*$$/' > $@ uv_constants.jl: ../src/uv_constants.h - $(QUIET_PERL) ${CC} -E -P "-I$(LIBUV_INC)" -DJULIA ../src/uv_constants.h | tail -n 12 > $@ + $(QUIET_PERL) ${CC} -E -P "-I$(LIBUV_INC)" -DJULIA ../src/uv_constants.h | tail -n 16 > $@ build_h.jl.phony: $(QUIET_PERL) $(CC) -E -P build.h -I../src/support | grep . > $@ diff --git a/base/poll.jl b/base/poll.jl index acc7535e20fc7..8e1fd8e25a943 100644 --- a/base/poll.jl +++ b/base/poll.jl @@ -6,9 +6,9 @@ type FileMonitor function FileMonitor(cb, file) handle = c_malloc(_sizeof_uv_fs_event) err = ccall(:jl_fs_event_init,Int32, (Ptr{Void}, Ptr{Void}, Ptr{Uint8}, Int32), eventloop(),handle,file,0) - if err == -1 + if err < 0 c_free(handle) - throw(UVError("FileMonitor")) + throw(UVError("FileMonitor",err)) end this = new(handle,cb,false,Condition()) associate_julia_struct(handle,this) @@ -41,9 +41,9 @@ type PollingFileWatcher <: UVPollingWatcher function PollingFileWatcher(cb, file) handle = c_malloc(_sizeof_uv_fs_poll) err = ccall(:uv_fs_poll_init,Int32,(Ptr{Void},Ptr{Void}),eventloop(),handle) - if err == -1 + if err < 0 c_free(handle) - throw(UVError("PollingFileWatcher")) + throw(UVError("PollingFileWatcher",err)) end this = new(handle, file, false, Condition(), cb) associate_julia_struct(handle,this) @@ -76,9 +76,9 @@ function FDWatcher(fd::RawFD) error("FD is already being watched by another watcher") end err = ccall(:uv_poll_init,Int32,(Ptr{Void},Ptr{Void},Int32),eventloop(),handle,fd.fd) - if err == -1 + if err < 0 c_free(handle) - throw(UVError("FDWatcher")) + throw(UVError("FDWatcher",err)) end this = FDWatcher(handle,fd,false,Condition(),false,0) associate_julia_struct(handle,this) @@ -89,9 +89,9 @@ end handle = c_malloc(_sizeof_uv_poll) err = ccall(:uv_poll_init_socket,Int32,(Ptr{Void}, Ptr{Void}, Ptr{Void}), eventloop(), handle, fd.handle) - if err == -1 + if err < 0 c_free(handle) - throw(UVError("FDWatcher")) + throw(UVError("FDWatcher",err)) end this = FDWatcher(handle,fd,false,Condition(),false,0) associate_julia_struct(handle,this) @@ -101,9 +101,9 @@ end function fdw_wait_cb(fdw::FDWatcher,status,events) if status == -1 - notify(fdw.notify,(UV_error_t(_uv_lasterror(),_uv_lastsystemerror()),events)) + notify_error(fdw.notify,UVError("FDWatcher",status)) else - notify(fdw.notify,(UV_error_t(int32(0),int32(0)),events)) + notify(fdw.notify,events) end end @@ -119,10 +119,7 @@ function _wait(fdw::FDWatcher,readable,writeable) start_watching(fdw_wait_cb,fdw,events) end while true - err, events = wait(fdw.notify) - if err.uv_code != 0 - throw(UVError("wait (FD)",err)) - end + events = wait(fdw.notify) if (readable && (events & UV_READABLE) != 0) || (writeable && (events & UV_WRITEABLE) != 0) break @@ -180,10 +177,10 @@ let end function pfw_wait_cb(pfw::PollingFileWatcher, status, prev, cur) - if status == -1 - notify(pfw.notify,(UV_error_t(_uv_lasterror(),_uv_lastsystemerror()),prev,cur)) + if status < 0 + notify_error(pfw.notify,UVError("PollingFileWatcher",status)) else - notify(pfw.notify,(UV_error_t(int32(0),int32(0)),prev,cur)) + notify(pfw.notify,(prev,cur)) end end @@ -191,10 +188,7 @@ function wait(pfw::PollingFileWatcher; interval=3.0) if !pfw.open start_watching(pfw_wait_cb,pfw,interval) end - err,prev,curr = wait(pfw.notify) - if err.uv_code != 0 - throw(UVError("wait (PollingFileWatcher)",err)) - end + prev,curr = wait(pfw.notify) if isempty(pfw.notify.waitq) stop_watching(pfw) end @@ -203,9 +197,6 @@ end function wait(m::FileMonitor) err, filename, events = wait(m.notify) - if err.uv_code != 0 - throw(UVError("wait (FileMonitor)",err)) - end filename, events end @@ -246,9 +237,9 @@ function _uv_hook_fseventscb(t::FileMonitor,filename::Ptr,events::Int32,status:: # bytestring(convert(Ptr{Uint8},filename)) - seems broken at the moment - got NULL t.cb(status, events, status) if status == -1 - notify(t.notify,(UV_error_t(_uv_lasterror(),_uv_lastsystemerror()),bytestring(convert(Ptr{Uint8},filename)),events)) + notify_error(t.notify,UVError("FileMonitor",status)) else - notify(t.notify,(UV_error_t(int32(0),int32(0)),bytestring(convert(Ptr{Uint8},filename)),events)) + notify(t.notify,events) end end end diff --git a/base/process.jl b/base/process.jl index ce9ca3c35eb9f..47092dfa380cb 100644 --- a/base/process.jl +++ b/base/process.jl @@ -196,7 +196,7 @@ function _jl_spawn(cmd::Ptr{Uint8}, argv::Ptr{Ptr{Uint8}}, loop::Ptr{Void}, pp:: pp.cmd.detach, pp.cmd.env === nothing ? C_NULL : pp.cmd.env) if error != 0 c_free(proc) - throw(UVError("spawn")) + throw(UVError("spawn",error)) end associate_julia_struct(proc,pp) return proc @@ -451,6 +451,7 @@ end _jl_kill(p::Process,signum::Integer) = ccall(:uv_process_kill,Int32,(Ptr{Void},Int32),p.handle,signum) function kill(p::Process,signum::Integer) if process_running(p) + @assert p.handle != C_NULL _jl_kill(p, signum) else int32(-1) diff --git a/base/socket.jl b/base/socket.jl index c39ef0bbb3660..d929f305f5cce 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -256,11 +256,12 @@ type TcpSocket <: Socket end function TcpSocket() this = TcpSocket(c_malloc(_sizeof_uv_tcp)) - if 0 != ccall(:uv_tcp_init,Cint,(Ptr{Void},Ptr{Void}), + err = ccall(:uv_tcp_init,Cint,(Ptr{Void},Ptr{Void}), eventloop(),this.handle) + if err != 0 c_free(this.handle) this.handle = C_NULL - error(UVError("Failed to create tcp socket")) + error(UVError("Failed to create tcp socket",err)) end associate_julia_struct(this.handle, this) this.status = StatusInit @@ -282,11 +283,12 @@ type TcpServer <: UVServer end function TcpServer() this = TcpServer(c_malloc(_sizeof_uv_tcp)) - if 0 != ccall(:uv_tcp_init,Cint,(Ptr{Void},Ptr{Void}), + err = ccall(:uv_tcp_init,Cint,(Ptr{Void},Ptr{Void}), eventloop(),this.handle) + if err != 0 c_free(this.handle) this.handle = C_NULL - error(UVError("Failed to create tcp server")) + error(UVError("Failed to create tcp server",err)) end associate_julia_struct(this.handle, this) this.status = StatusInit @@ -332,16 +334,13 @@ accept(server::PipeServer) = accept(server, NamedPipe()) bind(sock::TcpServer, addr::InetAddr) = bind(sock,addr.host,addr.port) bind(sock::TcpServer, host::IpAddr, port) = bind(sock, InetAddr(host,port)) -const UV_SUCCESS = 0 -const UV_EACCES = 3 -const UV_EADDRINUSE = 5 - function bind(sock::TcpServer, host::IPv4, port::Uint16) @assert sock.status == StatusInit - if 0 != ccall(:jl_tcp_bind, Int32, (Ptr{Void}, Uint16, Uint32), + err = ccall(:jl_tcp_bind, Int32, (Ptr{Void}, Uint16, Uint32), sock.handle, hton(port), hton(host.host)) - if (err=_uv_lasterror()) != UV_EADDRINUSE && err != UV_EACCES - error(UVError("bind")) + if err < 0 + if err != UV_EADDRINUSE && err != UV_EACCES + error(UVError("bind",err)) else return false end @@ -352,10 +351,11 @@ end function bind(sock::TcpServer, host::IPv6, port::Uint16) @assert sock.status == StatusInit - if 0 != ccall(:jl_tcp_bind6, Int32, (Ptr{Void}, Uint16, Ptr{Uint128}), + err = ccall(:jl_tcp_bind6, Int32, (Ptr{Void}, Uint16, Ptr{Uint128}), sock.handle, hton(port), &hton(host.host)) - if (err=_uv_lasterror()) != UV_EADDRINUSE && err != UV_EACCES - error(UVError("bind")) + if err < 0 + if err != UV_EADDRINUSE && err != UV_EACCES + error(UVError("bind",err)) else return false end @@ -369,7 +369,7 @@ callback_dict = ObjectIdDict() function _uv_hook_getaddrinfo(cb::Function, addrinfo::Ptr{Void}, status::Int32) delete!(callback_dict,cb) if status != 0 || addrinfo == C_NULL - cb(UVError("getaddrinfo callback")) + cb(UVError("getaddrinfo callback",status)) return end freeaddrinfo = addrinfo @@ -414,7 +414,7 @@ function getipaddr() addr, count = addr[1],count[1] if err != 0 ccall(:uv_free_interface_addresses,Void,(Ptr{Uint8},Int32),addr,count) - throw(UVError("getlocalip",err,0)) + throw(UVError("getlocalip",err)) end for i = 0:(count-1) current_addr = addr + i*_sizeof_uv_interface_address @@ -479,12 +479,12 @@ end ## -listen(sock::UVServer; backlog::Integer=BACKLOG_DEFAULT) = (uv_error("listen",!listen!(sock;backlog=backlog)); sock) +listen(sock::UVServer; backlog::Integer=BACKLOG_DEFAULT) = (uv_error("listen",_listen(sock;backlog=backlog)); sock) function listen(addr; backlog::Integer=BACKLOG_DEFAULT) sock = TcpServer() - uv_error("listen",!bind(sock,addr)) - uv_error("listen",!listen!(sock;backlog=backlog)) + !bind(sock,addr) && error("Cannot bind to port (may already be in use or access denied)") + uv_error("listen",_listen(sock;backlog=backlog)) sock end listen(port::Integer; backlog::Integer=BACKLOG_DEFAULT) = listen(IPv4(uint32(0)),port;backlog=backlog) @@ -505,7 +505,7 @@ function accept_nonblock(server::TcpServer,client::TcpSocket) end function accept_nonblock(server::TcpServer) client = TcpSocket() - uv_error("accept", accept_nonblock(server, client) == -1) + uv_error("accept", accept_nonblock(server, client)) client end @@ -516,15 +516,10 @@ function open_any_tcp_port(cb::Callback,default_port) while true sock = TcpServer() sock.ccb = cb - if (bind(sock,addr) && listen!(sock)) + if (bind(sock,addr) && _listen(sock) == 0) return (addr.port,sock) end - err = _uv_lasterror() - system = _uv_lastsystemerror() close(sock) - if (err != UV_SUCCESS && err != UV_EADDRINUSE && err != UV_EACCES) - throw(UVError("open_any_tcp_port",err,system)) - end addr.port += 1 if (addr.port==default_port) error("Not a single port is available.") diff --git a/base/stat.jl b/base/stat.jl index 1eeb0d3524a19..a47417033ec21 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -37,9 +37,7 @@ macro stat_call(sym,arg1type,arg) quote fill!(stat_buf,0) r = ccall($(Expr(:quote,sym)), Int32, ($arg1type,Ptr{Uint8}), $arg, stat_buf) - uv_errno = _uv_lasterror(eventloop()) - ENOENT, ENOTDIR = 34, 27 - systemerror(:stat, r!=0 && uv_errno!=ENOENT && uv_errno!=ENOTDIR) + systemerror(:stat, r!=0 && r!=UV_ENOENT && r!=UV_ENOTDIR) st = Stat(stat_buf) if ispath(st) != (r==0) error("WTF: stat returned zero type for a valid path!?") diff --git a/base/stream.jl b/base/stream.jl index e6a70c0171df3..f045595c62c75 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -130,9 +130,7 @@ function init_pipe!(pipe::Union(NamedPipe,PipeServer);readable::Bool=false,write if pipe.handle == C_NULL || pipe.status != StatusUninit error("Failed to initialize pipe") end - if 0 != ccall(:jl_init_pipe, Cint, (Ptr{Void},Int32,Int32,Int32,Any), pipe.handle, writeable,readable,julia_only,pipe) - throw(UVError("init_pipe")) - end + uv_error("init_pipe",ccall(:jl_init_pipe, Cint, (Ptr{Void},Int32,Int32,Int32,Any), pipe.handle, writeable,readable,julia_only,pipe)) pipe.status = StatusInit pipe end @@ -276,7 +274,7 @@ function _uv_hook_connectcb(sock::AsyncStream, status::Int32) err = () else sock.status = StatusInit - err = UVError("connect") + err = UVError("connect",status) end if isa(sock.ccb,Function) sock.ccb(sock, status) @@ -290,7 +288,7 @@ function _uv_hook_connectioncb(sock::UVServer, status::Int32) if status != -1 err = () else - err = UVError("connection") + err = UVError("connection",status) end if isa(sock.ccb,Function) sock.ccb(sock,status) @@ -335,9 +333,9 @@ function notify_filled(stream::AsyncStream, nread::Int) end function _uv_hook_readcb(stream::AsyncStream, nread::Int, base::Ptr{Void}, len::Int32) - if nread == -1 - if _uv_lasterror() != 1 #UV_EOF == 1 - err = UVError("readcb") + if nread < 0 + if nread != UV_EOF + err = UVError("readcb",nread) close(stream) notify_error(stream.readnotify, err) else @@ -372,10 +370,11 @@ type IdleAsyncWork <: AsyncWork cb::Function function IdleAsyncWork(cb::Function) this = new(c_malloc(_sizeof_uv_idle), cb) - if 0 != ccall(:uv_idle_init,Cint,(Ptr{Void},Ptr{Void}),eventloop(),this) + err = ccall(:uv_idle_init,Cint,(Ptr{Void},Ptr{Void}),eventloop(),this) + if err != 0 c_free(this.handle) this.handle = C_NULL - error(UVError("uv_make_timer")) + error(UVError("uv_make_timer",err)) end finalizer(this,close) this @@ -387,10 +386,11 @@ type TimeoutAsyncWork <: AsyncWork cb::Function function TimeoutAsyncWork(cb::Function) this = new(c_malloc(_sizeof_uv_timer), cb) - if 0 != ccall(:uv_timer_init,Cint,(Ptr{Void},Ptr{Void}),eventloop(),this.handle) + err = ccall(:uv_timer_init,Cint,(Ptr{Void},Ptr{Void}),eventloop(),this.handle) + if err != 0 c_free(this.handle) this.handle = C_NULL - error(UVError("uv_make_timer")) + error(UVError("uv_make_timer",err)) end finalizer(this,close) this @@ -447,7 +447,13 @@ end function sleep(sec::Real) w = Condition() - timer = TimeoutAsyncWork((tmr,status)->notify(w, status!=0?UVError("timer"):())) + timer = TimeoutAsyncWork(function (tmr,status) + if status == 0 + notify(w) + else + notify_error(UVError("timer",status)) + end + end) start_timer(timer, float(sec), 0) try wait(w) @@ -489,15 +495,9 @@ malloc_pipe() = c_malloc(_sizeof_uv_named_pipe) function link_pipe(read_end::Ptr{Void},readable_julia_only::Bool,write_end::Ptr{Void},writeable_julia_only::Bool,readpipe::AsyncStream,writepipe::AsyncStream) #make the pipe an unbuffered stream for now #TODO: this is probably not freeing memory properly after errors - if 0 != ccall(:jl_init_pipe, Cint, (Ptr{Void},Int32,Int32,Int32,Any), read_end, 0, 1, readable_julia_only, readpipe) - error(UVError("init_pipe")) - end - if 0 != ccall(:jl_init_pipe, Cint, (Ptr{Void},Int32,Int32,Int32,Any), write_end, 1, 0, writeable_julia_only, writepipe) - error(UVError("init_pipe")) - end - if 0 != ccall(:uv_pipe_link, Int32, (Ptr{Void}, Ptr{Void}), read_end, write_end) - error(UVError("uv_pipe_link")) - end + uv_error("init_pipe",ccall(:jl_init_pipe, Cint, (Ptr{Void},Int32,Int32,Int32,Any), read_end, 0, 1, readable_julia_only, readpipe)) + uv_error("init_pipe(2)",ccall(:jl_init_pipe, Cint, (Ptr{Void},Int32,Int32,Int32,Any), write_end, 1, 0, writeable_julia_only, writepipe)) + uv_error("pipe_link",ccall(:uv_pipe_link, Int32, (Ptr{Void}, Ptr{Void}), read_end, write_end)) end function link_pipe(read_end2::NamedPipe,readable_julia_only::Bool,write_end::Ptr{Void},writeable_julia_only::Bool) @@ -628,13 +628,23 @@ end # finish_read(state...) #end +macro uv_write(n,call) + esc(quote + uvw = c_malloc(_sizeof_uv_write+$(n)) + err = $call + if err < 0 + c_free(uvw) + uv_error("write", err) + end + end) +end ## low-level calls ## function write!{T}(s::AsyncStream, a::Array{T}) if isbits(T) - req = ccall(:jl_write_no_copy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}), handle(s), a, uint(length(a)*sizeof(T)), uv_jl_writecb::Ptr{Void}) - uv_error("write", req == C_NULL) + n = uint(length(a)*sizeof(T)) + @uv_write n ccall(:jl_write_no_copy, Int32, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}, Ptr{Void}), handle(s), a, n, uvw, uv_jl_writecb::Ptr{Void}) return int(length(a)*sizeof(T)) else throw(MethodError(write,(s,a))) @@ -642,8 +652,7 @@ function write!{T}(s::AsyncStream, a::Array{T}) end function write!(s::AsyncStream, p::Ptr, nb::Integer) check_open(s) - req = ccall(:jl_write_no_copy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}), handle(s), p, nb, uv_jl_writecb::Ptr{Void}) - uv_error("write", req == C_NULL) + @uv_write nb ccall(:jl_write_no_copy, Int32, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}, Ptr{Void}), handle(s), p, nb, uvw, uv_jl_writecb::Ptr{Void}) return nb end write!(s::AsyncStream, string::ByteString) = write!(s,string.data) @@ -657,22 +666,22 @@ end function write(s::AsyncStream, b::Uint8) check_open(s) if isdefined(Main.Base,:Scheduler) && current_task() != Main.Base.Scheduler - req = ccall(:jl_putc_copy, Ptr{Void}, (Uint8, Ptr{Void}, Ptr{Void}), b, handle(s), uv_jl_writecb_task::Ptr{Void}) - uv_req_set_data(req,current_task()) + @uv_write 1 ccall(:jl_putc_copy, Int32, (Uint8, Ptr{Void}, Ptr{Void}, Ptr{Void}), b, handle(s), uvw, uv_jl_writecb_task::Ptr{Void}) + uv_req_set_data(uvw,current_task()) wait() else - req = ccall(:jl_putc_copy, Ptr{Void}, (Uint8, Ptr{Void}, Ptr{Void}), b, handle(s), uv_jl_writecb::Ptr{Void}) + @uv_write 1 ccall(:jl_putc_copy, Int32, (Uint8, Ptr{Void}, Ptr{Void}, Ptr{Void}), b, handle(s), uvw, uv_jl_writecb::Ptr{Void}) end return 1 end function write(s::AsyncStream, c::Char) check_open(s) if isdefined(Main.Base,:Scheduler) && current_task() != Main.Base.Scheduler - req = ccall(:jl_pututf8_copy, Ptr{Void}, (Ptr{Void},Uint32, Ptr{Void}), handle(s), c, uv_jl_writecb_task::Ptr{Void}) - uv_req_set_data(req,current_task()) + @uv_write utf8sizeof(c) ccall(:jl_pututf8_copy, Int32, (Ptr{Void},Uint32, Ptr{Void}, Ptr{Void}), handle(s), c, uvw, uv_jl_writecb_task::Ptr{Void}) + uv_req_set_data(uvw,current_task()) wait() else - req = ccall(:jl_pututf8_copy, Ptr{Void}, (Ptr{Void},Uint32, Ptr{Void}), handle(s), c, uv_jl_writecb::Ptr{Void}) + @uv_write utf8sizeof(c) ccall(:jl_pututf8_copy, Int32, (Ptr{Void},Uint32, Ptr{Void}, Ptr{Void}), handle(s), c, uvw, uv_jl_writecb::Ptr{Void}) end return utf8sizeof(c) end @@ -680,9 +689,9 @@ function write{T}(s::AsyncStream, a::Array{T}) check_open(s) if isbits(T) if isdefined(Main.Base,:Scheduler) && current_task() != Main.Base.Scheduler - req = ccall(:jl_write_no_copy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}), handle(s), a, uint(length(a)*sizeof(T)), uv_jl_writecb_task::Ptr{Void}) - uv_error("write", req == C_NULL) - uv_req_set_data(req,current_task()) + n = uint(length(a)*sizeof(T)) + @uv_write n ccall(:jl_write_no_copy, Int32, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}, Ptr{Void}), handle(s), a, n, uvw, uv_jl_writecb_task::Ptr{Void}) + uv_req_set_data(uvw,current_task()) wait() else write!(s,copy(a)) @@ -695,9 +704,8 @@ end function write(s::AsyncStream, p::Ptr, nb::Integer) check_open(s) if isdefined(Main.Base,:Scheduler) && current_task() != Main.Base.Scheduler - req = ccall(:jl_write_no_copy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}), handle(s), p, nb, uv_jl_writecb_task::Ptr{Void}) - uv_error("write", req == C_NULL) - uv_req_set_data(req,current_task()) + @uv_write nb ccall(:jl_write_no_copy, Int32, (Ptr{Void}, Ptr{Void}, Uint, Ptr{Void}, Ptr{Void}), handle(s), p, nb, uvw, uv_jl_writecb_task::Ptr{Void}) + uv_req_set_data(uvw,current_task()) wait() else ccall(:jl_write, Uint, (Ptr{Void},Ptr{Void},Uint), handle(s), p, uint(nb)) @@ -707,8 +715,8 @@ end function _uv_hook_writecb_task(s::AsyncStream,req::Ptr{Void},status::Int32) d = uv_req_data(req) - if status == -1 - err = UVError("write") + if status < 0 + err = UVError("write",status) close(s) if d != C_NULL notify_error(unsafe_pointer_to_objref(d)::Task,err) @@ -719,29 +727,17 @@ function _uv_hook_writecb_task(s::AsyncStream,req::Ptr{Void},status::Int32) end ## Libuv error handling ## -_uv_lasterror(loop::Ptr{Void}) = ccall(:jl_last_errno,Int32,(Ptr{Void},),loop) -_uv_lasterror() = _uv_lasterror(eventloop()) -_uv_lastsystemerror(loop::Ptr{Void}) = ccall(:jl_last_errno,Int32,(Ptr{Void},),loop) -_uv_lastsystemerror() = _uv_lasterror(eventloop()) - -type UV_error_t - uv_code::Int32 - system_code::Int32 -end type UVError <: Exception prefix::String - s::UV_error_t - UVError(p::String,e::UV_error_t)=new(p,e) + code::Int32 + UVError(p::String,code::Int32)=new(p,code) end -UVError(p::String) = UVError(p,_uv_lasterror(),_uv_lastsystemerror()) -UVError(p::String,uv::Integer,system::Integer) = UVError(p,UV_error_t(uv,system)) -struverror(err::UVError) = bytestring(ccall(:jl_uv_strerror,Ptr{Uint8},(Int32,Int32),err.s.uv_code,err.s.system_code)) -uverrorname(err::UVError) = bytestring(ccall(:jl_uv_err_name,Ptr{Uint8},(Int32,Int32),err.s.uv_code,err.s.system_code)) +struverror(err::UVError) = bytestring(ccall(:uv_strerror,Ptr{Uint8},(Int32,),err.code)) +uverrorname(err::UVError) = bytestring(ccall(:uv_err_name,Ptr{Uint8},(Int32,),err.code)) -uv_error(prefix, e::UV_error_t) = e.uv_code != 0 ? throw(UVError(string(prefix),e)) : nothing +uv_error(prefix, c::Int32) = c != 0 ? throw(UVError(string(prefix),c)) : nothing uv_error(prefix, b::Bool) = b ? throw(UVError(string(prefix))) : nothing -uv_error(prefix) = uv_error(prefix, _uv_lasterror() != 0) show(io::IO, e::UVError) = print(io, e.prefix*": "*struverror(e)*" ("*uverrorname(e)*")") @@ -761,17 +757,17 @@ function accept_nonblock(server::PipeServer) client end -const UV_EAGAIN = 4 function accept(server::UVServer, client::AsyncStream) if server.status != StatusActive error("accept: Server not connected. Did you `listen`?") end @assert client.status == StatusInit while true - if accept_nonblock(server,client) == 0 + err = accept_nonblock(server,client) + if err == 0 return client - elseif _uv_lasterror() != UV_EAGAIN - uv_error("accept") + elseif err != UV_EAGAIN + uv_error("accept",err) end wait(server.connectnotify) end @@ -779,22 +775,20 @@ end const BACKLOG_DEFAULT = 511 -function listen!(sock::UVServer; backlog::Integer=BACKLOG_DEFAULT) - if 0 == ccall(:uv_listen, Cint, (Ptr{Void}, Cint, Ptr{Void}), +function _listen(sock::UVServer; backlog::Integer=BACKLOG_DEFAULT) + err = ccall(:uv_listen, Cint, (Ptr{Void}, Cint, Ptr{Void}), sock.handle, backlog, uv_jl_connectioncb::Ptr{Void}) - sock.status = StatusActive - true - else - false - end + sock.status = StatusActive + err end function bind(server::PipeServer, name::ASCIIString) @assert server.status == StatusInit - if 0 != ccall(:uv_pipe_bind, Int32, (Ptr{Void}, Ptr{Uint8}), + err = ccall(:uv_pipe_bind, Int32, (Ptr{Void}, Ptr{Uint8}), server.handle, name) - if (err=_uv_lasterror()) != UV_EADDRINUSE && err != UV_EACCES - error(UVError("bind")) + if err != 0 + if err != UV_EADDRINUSE && err != UV_EACCES + error(UVError("bind",err)) else return false end @@ -806,8 +800,8 @@ end function listen(path::ByteString) sock = PipeServer() - uv_error("listen", !bind(sock, path)) - uv_error("listen", !listen!(sock)) + bind(sock, path) || error("Could not listen on path $path") + uv_error("listen", _listen(sock)) sock end diff --git a/deps/Makefile b/deps/Makefile index 3cb289eefeb3f..7b893afbdbfe9 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -393,48 +393,42 @@ install-readline: $(READLINE_OBJ_TARGET) ## LIBUV ## +UV_SRC_TARGET = libuv/libuv.a UV_OBJ_TARGET = $(BUILD)/lib/libuv.a -UV_OBJ_SOURCE = libuv/libuv.a -libuv/Makefile: +libuv/configure: (cd .. && git submodule init && git submodule update) +libuv/config.status: libuv/configure + cd libuv && \ + ./configure --with-pic $(CONFIGURE_COMMON) + touch -c $@ ifeq (exists, $(shell [ -d libuv/.git ] && echo exists )) -$(UV_OBJ_SOURCE): libuv/.git/HEAD +$(UV_SRC_TARGET): libuv/.git/HEAD endif ifeq (exists, $(shell [ -d $(JULIAHOME)/.git/modules/deps/libuv ] && echo exists )) -$(UV_OBJ_SOURCE): $(JULIAHOME)/.git/modules/deps/libuv/HEAD -endif -LIBUV_MAKE_FLAGS = -C libuv CC="$(CC)" AR="$(AR)" -ifeq ($(OS),WINNT) -LIBUV_MAKE_FLAGS += PLATFORM=mingw -else -ifneq ($(OS),$(BUILD_OS)) -$(error libuv may autodetect your cross-compile PLATFORM incorrectly) -endif +$(UV_SRC_TARGET): $(JULIAHOME)/.git/modules/deps/libuv/HEAD endif -$(UV_OBJ_SOURCE): libuv/Makefile - $(MAKE) clean $(LIBUV_MAKE_FLAGS) RUNNER_LIBS= - $(MAKE) libuv.a $(LIBUV_MAKE_FLAGS) +$(UV_SRC_TARGET): libuv/config.status + $(MAKE) -C libuv touch -c $@ -libuv/checked: $(LIBUV_OBJ_SOURCE) +libuv/checked: $(UV_SRC_TARGET) ifeq ($(OS),$(BUILD_OS)) - $(MAKE) test $(LIBUV_MAKE_FLAGS) + -$(MAKE) -C libuv check endif echo 1 > $@ -#todo: libuv tests are really slow -$(UV_OBJ_TARGET): $(UV_OBJ_SOURCE) - mkdir -p $(BUILD)/include - cp $(UV_OBJ_SOURCE) $(BUILD)/lib/ - cp -r libuv/include/* $(BUILD)/include +$(UV_OBJ_TARGET): $(UV_SRC_TARGET) libuv/checked + $(MAKE) -C libuv install + $(INSTALL_NAME_CMD)libuv.dylib $@ clean-uv: - -$(MAKE) clean $(LIBUV_MAKE_FLAGS) RUNNER_LIBS= + -$(MAKE) -C libuv clean RUNNER_LIBS= -rm -rf $(BUILD)/lib/libuv.a $(BUILD)/include/uv.h $(BUILD)/include/uv-private distclean-uv: clean-uv + -$(MAKE) -C libuv distclean -get-uv: libuv/Makefile -configure-uv: get-uv -compile-uv: $(UV_OBJ_SOURCE) +get-uv: libuv/configure +configure-uv: libuv/config.status +compile-uv: $(UV_SRC_TARGET) check-uv: libuv/checked install-uv: $(UV_OBJ_TARGET) diff --git a/deps/libuv b/deps/libuv index 37f91a541bae5..8d29577b20dcb 160000 --- a/deps/libuv +++ b/deps/libuv @@ -1 +1 @@ -Subproject commit 37f91a541bae53c877d3805f54ed801889e81516 +Subproject commit 8d29577b20dcb26a8cc1c1c1474e5f91a1cff348 diff --git a/src/jl_uv.c b/src/jl_uv.c index 712ce9d5dbdd2..5c3358c86d8d3 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -268,7 +268,7 @@ DLLEXPORT void jl_close_uv(uv_handle_t *handle) uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t)); int err = uv_shutdown(req, (uv_stream_t*)handle, &jl_uv_shutdownCallback); if (err != 0) { - printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop()))); + printf("shutdown err: %s\n", uv_strerror(err)); uv_close(handle, &jl_uv_closeHandle); } } @@ -434,23 +434,21 @@ DLLEXPORT void jl_uv_writecb_task(uv_write_t* req, int status) (void)ret; } -DLLEXPORT void *jl_write_copy(uv_stream_t *stream, const char *str, size_t n, void *writecb) +DLLEXPORT int jl_write_copy(uv_stream_t *stream, const char *str, size_t n, uv_write_t *uvw, void *writecb) { JL_SIGATOMIC_BEGIN(); - uv_write_t *uvw = malloc(sizeof(uv_write_t)+n); char *data = (char*)(uvw+1); memcpy(data,str,n); uv_buf_t buf[] = {{.base = data,.len=n}}; uvw->data = NULL; int err = uv_write(uvw,stream,buf,1,writecb); - if (err) - free(uvw); JL_SIGATOMIC_END(); - return err ? NULL : uvw; + return err; } DLLEXPORT int jl_putc(unsigned char c, uv_stream_t *stream) { + int err; if (stream!=0) { if (stream->typetype == UV_FILE) { @@ -458,12 +456,18 @@ DLLEXPORT int jl_putc(unsigned char c, uv_stream_t *stream) jl_uv_file_t *file = (jl_uv_file_t *)stream; // Do a blocking write for now uv_fs_t req; - int err = uv_fs_write(file->loop, &req, file->file, &c, 1, -1, NULL); + err = uv_fs_write(file->loop, &req, file->file, &c, 1, -1, NULL); JL_SIGATOMIC_END(); return err ? 0 : 1; } else { - return jl_write_copy(stream,(char*)&c,1,&jl_uv_writecb) == NULL ? 0 : 1; + uv_write_t *uvw = malloc(sizeof(uv_write_t)+1); + err = jl_write_copy(stream,(char*)&c,1,uvw,&jl_uv_writecb); + if (err < 0) { + free(uvw); + return 0; + } + return 1; } } else { @@ -474,22 +478,19 @@ DLLEXPORT int jl_putc(unsigned char c, uv_stream_t *stream) return 0; } -DLLEXPORT void *jl_write_no_copy(uv_stream_t *stream, char *data, size_t n, void *writecb) +DLLEXPORT int jl_write_no_copy(uv_stream_t *stream, char *data, size_t n, uv_write_t *uvw, void *writecb) { uv_buf_t buf[] = {{.base = data,.len=n}}; JL_SIGATOMIC_BEGIN(); - uv_write_t *uvw = malloc(sizeof(uv_write_t)); int err = uv_write(uvw,stream,buf,1,writecb); uvw->data = NULL; - if (err != 0) - free(uvw); JL_SIGATOMIC_END(); - return err ? NULL : uvw; + return err; } -DLLEXPORT void *jl_putc_copy(unsigned char c, uv_stream_t *stream, void *writecb) +DLLEXPORT int jl_putc_copy(unsigned char c, uv_stream_t *stream, void *uvw, void *writecb) { - return jl_write_copy(stream,(char *)&c,1,writecb); + return jl_write_copy(stream,(char *)&c,1,uvw,writecb); } DLLEXPORT int jl_pututf8(uv_stream_t *s, uint32_t wchar ) @@ -501,17 +502,18 @@ DLLEXPORT int jl_pututf8(uv_stream_t *s, uint32_t wchar ) return jl_write(s, buf, n); } -DLLEXPORT void *jl_pututf8_copy(uv_stream_t *s, uint32_t wchar, void *writecb) +DLLEXPORT int jl_pututf8_copy(uv_stream_t *s, uint32_t wchar, void *uvw, void *writecb) { char buf[8]; if (wchar < 0x80) - return jl_putc_copy((int)wchar, s, writecb); + return jl_putc_copy((int)wchar, s, uvw, writecb); size_t n = u8_toutf8(buf, 8, &wchar, 1); - return jl_write_copy(s, buf, n, writecb); + return jl_write_copy(s, buf, n, uvw, writecb); } DLLEXPORT size_t jl_write(uv_stream_t *stream, const char *str, size_t n) { + int err; //TODO: BAD!! Needed because Julia can't yet detect null stdio if (stream == 0) return 0; @@ -521,12 +523,18 @@ DLLEXPORT size_t jl_write(uv_stream_t *stream, const char *str, size_t n) jl_uv_file_t *file = (jl_uv_file_t *)stream; // Do a blocking write for now uv_fs_t req; - int err = uv_fs_write(file->loop, &req, file->file, (void*)str, n, -1, NULL); + err = uv_fs_write(file->loop, &req, file->file, (void*)str, n, -1, NULL); JL_SIGATOMIC_END(); return err ? 0 : n; } else { - return jl_write_copy(stream,str,n,&jl_uv_writecb) == NULL ? 0 : n; + uv_write_t *uvw = malloc(sizeof(uv_write_t)+n); + err = jl_write_copy(stream,str,n,uvw,&jl_uv_writecb); + if (err < 0) { + free(uvw); + return 0; + } + return n; } } else { @@ -587,7 +595,7 @@ DLLEXPORT void jl_exit(int exitcode) DLLEXPORT int jl_cwd(char *buffer, size_t size) { - return (uv_cwd(buffer,size)).code; + return uv_cwd(buffer,size); } DLLEXPORT int jl_getpid() @@ -626,7 +634,7 @@ DLLEXPORT int jl_uv_sizeof_interface_address() DLLEXPORT int jl_uv_interface_addresses(uv_interface_address_t **ifAddrStruct,int *count) { - return uv_interface_addresses(ifAddrStruct,count).code; + return uv_interface_addresses(ifAddrStruct,count); } DLLEXPORT int jl_uv_interface_address_is_internal(uv_interface_address_t *addr) @@ -742,28 +750,6 @@ DLLEXPORT int jl_connect_raw(uv_tcp_t *handle,struct sockaddr_storage *addr) return -2; //error! Only IPv4 and IPv6 are implemented atm } -DLLEXPORT int jl_last_errno(uv_loop_t *loop) -{ - return (uv_last_error(loop)).code; -} - -DLLEXPORT int jl_last_system_errno(uv_loop_t *loop) -{ - return (uv_last_error(loop)).sys_errno_; -} - -DLLEXPORT const char *jl_uv_strerror(int a, int b) -{ - uv_err_t err = {a,b}; - return uv_strerror(err); -} - -DLLEXPORT const char *jl_uv_err_name(int a, int b) -{ - uv_err_t err = {a,b}; - return uv_err_name(err); -} - DLLEXPORT char *jl_ios_buf_base(ios_t *ios) { return ios->buf; diff --git a/src/uv_constants.h b/src/uv_constants.h index 4cdd59df44ee8..c6d7bcd1bcb73 100644 --- a/src/uv_constants.h +++ b/src/uv_constants.h @@ -2,6 +2,9 @@ #define XX(uc,lc) :UV_##uc, const uv_handle_types = [UV_HANDLE_TYPE_MAP(XX) :UV_FILE] const uv_req_types = [UV_REQ_TYPE_MAP(XX)] +#undef XX +#define XX(uc,lc) (:UV_##uc,UV__##uc), +const uv_err_vals = [UV_ERRNO_MAP(XX)] let handles = [:UV_UNKNOWN_HANDLE, uv_handle_types, :UV_HANDLE_TYPE_MAX, :UV_RAW_FD, :UV_RAW_HANDLE] reqs = [:UV_UNKNOWN_REQ, uv_req_types, :UV_REQ_TYPE_PRIVATE,:UV_REQ_TYPE_MAX] @@ -11,4 +14,7 @@ let for i=0:(length(reqs)-1) @eval const $(reqs[i+1]) = $i end -end \ No newline at end of file + for (v,val) in uv_err_vals + @eval const $v = $val + end +end diff --git a/test/socket.jl b/test/socket.jl index 4a6878351d19e..e62089bbc0d32 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -27,7 +27,7 @@ c = Base.Condition() @async begin - s = listen(2000) + s = listen(2134) Base.notify(c) sock = accept(s) write(sock,"Hello World\n") @@ -35,12 +35,12 @@ c = Base.Condition() close(sock) end wait(c) -@test readall(connect(2000)) == "Hello World\n" +@test readall(connect(2134)) == "Hello World\n" c = Base.Condition() @async begin server = Base.TcpServer() - bind(server,IPv4(0),2001) + bind(server,IPv4(0),2135) listen(server) Base.notify(c) sock = accept(server) @@ -49,7 +49,7 @@ c = Base.Condition() close(sock) end wait(c) -@test readall(connect(2001)) == "Hello World\n" +@test readall(connect(2135)) == "Hello World\n" isfile("testsocket") && Base.FS.unlink("testsocket") @async begin diff --git a/test/spawn.jl b/test/spawn.jl index ad0c27fbe620d..6101a7e6f904a 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -33,7 +33,8 @@ a = Base.Condition() Base.notify(a,p) @test !Base.wait_success(p) end -kill(wait(a)) +p = wait(a) +kill(p) @test_throws run(`foo`)