From f10e96c8d32b0e60e38e56321a082136f81a18d8 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Fri, 6 Aug 2021 15:36:52 -0400 Subject: [PATCH 1/2] Revert "upgrade libuv to v2-1.42.0 (#41710)" This reverts commit b50bf04ac0c59ede44fd230b2e1be5f18a29654f. --- Make.inc | 4 --- Makefile | 3 -- contrib/refresh_checksums.mk | 5 --- deps/checksums/libuv | 68 +++++++++++++++++------------------ deps/libuv.version | 4 +-- stdlib/LibUV_jll/Project.toml | 2 +- 6 files changed, 37 insertions(+), 49 deletions(-) diff --git a/Make.inc b/Make.inc index 33bfac180a0fa..504ceced40e47 100644 --- a/Make.inc +++ b/Make.inc @@ -90,10 +90,6 @@ endef COMMA:=, SPACE:=$(eval) $(eval) -# force a sane / stable configuration -export LC_ALL=C -export LANG=C - # We need python for things like BB triplet recognition and relative path computation. # We don't really care about version, generally, so just find something that works: PYTHON := "$(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null || echo "{python|python3|python2} not found")" diff --git a/Makefile b/Makefile index 62afa8e685529..51bb09b094f1c 100644 --- a/Makefile +++ b/Makefile @@ -573,6 +573,3 @@ endif @time $(call spawn,$(build_bindir)/julia$(EXE) -e '') @time $(call spawn,$(build_bindir)/julia$(EXE) -e '') @time $(call spawn,$(build_bindir)/julia$(EXE) -e '') - -print-locale: - @locale diff --git a/contrib/refresh_checksums.mk b/contrib/refresh_checksums.mk index 5b8a25ab79b91..1ccbb16a9ba4f 100644 --- a/contrib/refresh_checksums.mk +++ b/contrib/refresh_checksums.mk @@ -8,11 +8,6 @@ SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) JULIAHOME := $(abspath $(SRCDIR)/..) -# force a sane / stable configuration -export LC_ALL=C -export LANG=C -.SUFFIXES: - # Default target that will have everything else added to it as a dependency all: checksum pack-checksum diff --git a/deps/checksums/libuv b/deps/checksums/libuv index f3ecef6586547..f03a3c6ce9a35 100644 --- a/deps/checksums/libuv +++ b/deps/checksums/libuv @@ -1,34 +1,34 @@ -LibUV.v2.0.1+3.aarch64-apple-darwin.tar.gz/md5/7c1f08965b45726099a940ab28a79207 -LibUV.v2.0.1+3.aarch64-apple-darwin.tar.gz/sha512/9f9d170fc36e2e30c53e96cdf9ae7cd4eb969905db65119627d4a9e10abb5e41aeb4ab07705d571300d44d4894c9d179c6a9450e3e6415042a6131bae0971c26 -LibUV.v2.0.1+3.aarch64-linux-gnu.tar.gz/md5/8d59850a63ea71c4007d08f7d23ceda2 -LibUV.v2.0.1+3.aarch64-linux-gnu.tar.gz/sha512/f662b36ce6e336e724c6fd03482d91a70e7ae8cfe7a1fff98cbca2cdb99b0cd3475bf32e57547097ca625c1fceb57c989871f391faea9227a6d6d4faf7649175 -LibUV.v2.0.1+3.aarch64-linux-musl.tar.gz/md5/3ad43e49a7a996b50341e7150064f13d -LibUV.v2.0.1+3.aarch64-linux-musl.tar.gz/sha512/69c6675fee6647eb7a2c8c680bd49ba31c1dcda676530af1ad1ca979c0cf8d9c908e0cb246608718d4bbca4d73174751c608aa80e3f11557ed4d05cc1d270021 -LibUV.v2.0.1+3.armv6l-linux-gnueabihf.tar.gz/md5/fec375c1c45fbd1b2eb22fbd5f727e5f -LibUV.v2.0.1+3.armv6l-linux-gnueabihf.tar.gz/sha512/1b279406cdb43bf1c3fd6b1d2d24fe9b5ca75a65212b5720d5406af26a6b7551b18efb0471c884e98e97c50693412344fd733c3ef19ea8fecf1c2c26ae888492 -LibUV.v2.0.1+3.armv6l-linux-musleabihf.tar.gz/md5/07790f330f3394d0a3ea47aa56529be1 -LibUV.v2.0.1+3.armv6l-linux-musleabihf.tar.gz/sha512/4fd4bf7c1b333907fbbbfdca213c91cb6b387e56886b6349271d7a3c1ddb3f9349f0799c60178de507e039289662c310829d81be804c5076ce9ae16eb61c8cb1 -LibUV.v2.0.1+3.armv7l-linux-gnueabihf.tar.gz/md5/2ce38a69564e279b0deb32a6af1acc52 -LibUV.v2.0.1+3.armv7l-linux-gnueabihf.tar.gz/sha512/d520ef8c556db6a42534c4abdd59f4b64ebd77cdb7b2972385d6a90463e0a490ca168bb83128e66b13555128305f85d5c979a739f7c369a11f8217e49505ce0a -LibUV.v2.0.1+3.armv7l-linux-musleabihf.tar.gz/md5/034d903cb13a45278df742df23c46275 -LibUV.v2.0.1+3.armv7l-linux-musleabihf.tar.gz/sha512/f900fd47320628ac3cf0ba0b9d9408ef4e46ed508f5efc00b94b532c5d713fcf4695827f978f605b3d9f0a1db42abcd0b1fec6a6c5bb6a502ed5f0fed55f4a32 -LibUV.v2.0.1+3.i686-linux-gnu.tar.gz/md5/60c51d15d9ae2ac8418b71730dc093d0 -LibUV.v2.0.1+3.i686-linux-gnu.tar.gz/sha512/84841f6fb4c744e335d6ce25e3059d9aeeaa54b823fe714f43fa8b11caf209e539afb9605e96992d075ae16a664da6c3a3c3d4cdb905d42c0ddc8722267c19af -LibUV.v2.0.1+3.i686-linux-musl.tar.gz/md5/d70ffffd8e57dfbcb4265ad202722fca -LibUV.v2.0.1+3.i686-linux-musl.tar.gz/sha512/c76dc0df03f7a683e08313baa0d8471b45c64099e13cf71a6595cb50c9e8ff1e96c31c400f83144ee816e5a7c8f01ad6f48d8b50a6cd161e0d246737780c2a9e -LibUV.v2.0.1+3.i686-w64-mingw32.tar.gz/md5/aa634a6e49c5683dcca287f2cf1ac71e -LibUV.v2.0.1+3.i686-w64-mingw32.tar.gz/sha512/ac1b2b53cbd7e317866259c30de349c453deda2c970587e4f4b40605f966f722fe8250e9dd7677ded0c928c9398240b7e4867805bb1404fb9d0c7dfab8493c79 -LibUV.v2.0.1+3.powerpc64le-linux-gnu.tar.gz/md5/9233d6bb298bd5020b680c25f742de98 -LibUV.v2.0.1+3.powerpc64le-linux-gnu.tar.gz/sha512/172253d1e6ce888865f5fd2182aad6426ff9988313937c7abe80ccdba859289f7ec8997574bb853f9786596d90414c4a926a475c1817c17574e0dd2ea8ad68ad -LibUV.v2.0.1+3.x86_64-apple-darwin.tar.gz/md5/09b83fe0ced427136ea5680cea64b004 -LibUV.v2.0.1+3.x86_64-apple-darwin.tar.gz/sha512/1842df6b14f23cc42c1d29546aa00b4b07390646beb312092bceb00d1de855116368ddcdd4ccd8525741fb6ecd26312c90dc9342d2e1ef4d36fbb896bdd2cbd3 -LibUV.v2.0.1+3.x86_64-linux-gnu.tar.gz/md5/d54b4fbfd998228e80c42c89df2c14a1 -LibUV.v2.0.1+3.x86_64-linux-gnu.tar.gz/sha512/290b2432e72712e73f20aa0ea6f787f9ffbf9ab5e3249c708355f7d57fb3b40ec3913e0c9a7141197caf3a741d6edbb1788cdef7e1a9a8547117dcf40559e567 -LibUV.v2.0.1+3.x86_64-linux-musl.tar.gz/md5/7690b83baecf1b614f30c7c0b661d86d -LibUV.v2.0.1+3.x86_64-linux-musl.tar.gz/sha512/53950b56f87ea0acc13790bf3a82441ca4ccfcd66cf272c81915e999487e4973c8c474caa811584d5fa8873cdd18ac0944f3d6f415c483a26e38645eb1701cdb -LibUV.v2.0.1+3.x86_64-unknown-freebsd.tar.gz/md5/6d2a330a2e87b9b8564708fba963845f -LibUV.v2.0.1+3.x86_64-unknown-freebsd.tar.gz/sha512/f15daf2f5a1bda49234fe546e13f97280c843d6939c26c9f05133302ec81e38bd47a5098d4900e39290f913835cffbdaa0b2c6406d6a86dc2eb8d0159f461e9f -LibUV.v2.0.1+3.x86_64-w64-mingw32.tar.gz/md5/4f934cf8dd1d45b206af6a72c3e679f7 -LibUV.v2.0.1+3.x86_64-w64-mingw32.tar.gz/sha512/36ef56923d7cf5c31aba87fb75774ce68976f7b6b7971a4c86011da275a5472e28033a6d97b965887b7bbe335bedfb6970618b88f20c095228ffa5f783ab8eb1 -libuv-c6869fba163a1e04af64ede438a8fd0191e75e9e.tar.gz/md5/b60fc7b00bdfafcbbc66317858882058 -libuv-c6869fba163a1e04af64ede438a8fd0191e75e9e.tar.gz/sha512/197b386af51eb4456ce65e2951e033731e1194fca8bed08755a78360ebb3431ab4d8d69a75279e7995d2e4197133d613892e5b9b5d6411bffa692df35542420f +libuv-fb3e3364c33ae48c827f6b103e05c3f0e78b79a9.tar.gz/md5/dc93ae5119c8934f374570342ef036ed +libuv-fb3e3364c33ae48c827f6b103e05c3f0e78b79a9.tar.gz/sha512/29947c236aef8931be4767df1cd8404ee9b036ee107b31cbce6fad9a97743df57d068b15bc4bd00320b9b81cd879258a9ec9dc675853e424ccdb8d6bdd226240 +LibUV.v2.0.1+2.aarch64-apple-darwin.tar.gz/md5/ed00585eb80fd82c014e2a431269ccec +LibUV.v2.0.1+2.aarch64-apple-darwin.tar.gz/sha512/a98ffde4ff49a71699f798622c62b5f95d0dc010f1de88ad57ee437baa73cb25e263a8a6c4de86364fb31076993326d9bd0223db3e1ecf6904c1aa6e7e1f0120 +LibUV.v2.0.1+2.aarch64-linux-gnu.tar.gz/md5/3e75495795d5a4eee8ec9c1619a5caaa +LibUV.v2.0.1+2.aarch64-linux-gnu.tar.gz/sha512/c0f1396ccc7784772d4c40f3a62d6bb22c6859a3258b07727348f436b7991a8f6d51ec46c09569f17a7bd600a321ab3b3cd59538d39c228cd3e205c33e755a51 +LibUV.v2.0.1+2.aarch64-linux-musl.tar.gz/md5/c2899ea791cfcd37ff85c1182330168e +LibUV.v2.0.1+2.aarch64-linux-musl.tar.gz/sha512/b340ff4e28a5e566ee2640926265b2070acfcc4b3c87fc2e414e2b2a9ff23be852d92ff4f51e36e21de029f23bca5524e7e267ba091401b070f4d5cd9bd03c54 +LibUV.v2.0.1+2.armv6l-linux-gnueabihf.tar.gz/md5/6b6c080a88050051100af58a4e96f25d +LibUV.v2.0.1+2.armv6l-linux-gnueabihf.tar.gz/sha512/936a4f4baf21a0fe7492bc3fab3475f653824daa184030df764af1eb5e71d152aa5dd3449b1cf31f77a460169853d7371597056e641c440c7b3d4f5c6be1ce10 +LibUV.v2.0.1+2.armv6l-linux-musleabihf.tar.gz/md5/032010ad683931906d2467753cebea9e +LibUV.v2.0.1+2.armv6l-linux-musleabihf.tar.gz/sha512/b8050662775d75e59b072c688ae44f7a3d3f54d114270902a825e01f4d74c8e131a3a75cd95e31b9ebf4488d64ff6170a67e5986e02e5fcb105bf5d3cc28706b +LibUV.v2.0.1+2.armv7l-linux-gnueabihf.tar.gz/md5/e558bedc0b69d6575e43df0eec958ad9 +LibUV.v2.0.1+2.armv7l-linux-gnueabihf.tar.gz/sha512/d3404b20b7e8e8fe935ca1e7da55823a6ff6703c822acf622638dc5c744bfefe1745e8e3a67054abc3aec0c10793ac46dbab29ccf7269d8a3a0d857e3a1a93e7 +LibUV.v2.0.1+2.armv7l-linux-musleabihf.tar.gz/md5/1aa605d9930ba63874483defb35a96ba +LibUV.v2.0.1+2.armv7l-linux-musleabihf.tar.gz/sha512/927e710191e6b8d1c09054780b4af6336c6744ceb0885c7a5a0cec5e08bfb0d53ede75cc8bb145fda08f720d98a77e102a2903e08a0fef75a0b630631db6f35e +LibUV.v2.0.1+2.i686-linux-gnu.tar.gz/md5/4ec3415ef12615581f8b26ec374a35bf +LibUV.v2.0.1+2.i686-linux-gnu.tar.gz/sha512/fd37bb83cda297ec80332cdaed2a704ea43c3ec72fb539042ef09aa510275a0418c750278fca9e463bdecdca957f8457103f0be6eeae1017387141eb2b906694 +LibUV.v2.0.1+2.i686-linux-musl.tar.gz/md5/f24ea24837ef06be346d239cbb33ae7e +LibUV.v2.0.1+2.i686-linux-musl.tar.gz/sha512/e9388568b20fa71d95e331a336aa3b17396e87d99aef6d752cb48416cdc9501e2ea887702a5765a22dcf6b5f7b730f5666ed3a639e7fe0113e9032f0d760b352 +LibUV.v2.0.1+2.i686-w64-mingw32.tar.gz/md5/890d1f7963a5dc927c15f8433b69dcf7 +LibUV.v2.0.1+2.i686-w64-mingw32.tar.gz/sha512/7e7d2b6405bbb1b62725a61d649fcbd53c2dcb65b8a6deea5a186717f88dbab4198a0f58d4223500aa991976725f8e1c4272ab29866174c5f555ba75a2e9b0ee +LibUV.v2.0.1+2.powerpc64le-linux-gnu.tar.gz/md5/7fa0d0e9344f4a4c4d5075ec5d368b0a +LibUV.v2.0.1+2.powerpc64le-linux-gnu.tar.gz/sha512/b5587e9e1072bc6becd5d1354294a3afcfda1c52e9a5f56387d43c7300369106059a2bac8669a919ce25d888b2302711c7433a82e366648935481568420daeef +LibUV.v2.0.1+2.x86_64-apple-darwin.tar.gz/md5/716960539cbae1e38e1cf88c2670927d +LibUV.v2.0.1+2.x86_64-apple-darwin.tar.gz/sha512/7b064d99428b312302c698e73e8a7919147c0522857a24e08d16144aea83429c5ac9526b6553697f28784457a5b417958fc5e4e28b4191861004dddc3f95566c +LibUV.v2.0.1+2.x86_64-linux-gnu.tar.gz/md5/ff70887943a3fc68eddcb66ed941417e +LibUV.v2.0.1+2.x86_64-linux-gnu.tar.gz/sha512/00610022d700dd6b33c97decea43490fcd4218fde2e57c0d6317abec046adf220fdf4d03f132938ec78af85653a5262d1344527c632c06aec53750710a6b317c +LibUV.v2.0.1+2.x86_64-linux-musl.tar.gz/md5/a5834444d0b7e7d88cc87e5eb458bca3 +LibUV.v2.0.1+2.x86_64-linux-musl.tar.gz/sha512/e2e6e6726e8ef0962c35d7ff54a60b3370cd5b927fda8b4415e8d2f19b098ed9bd00e262eb18d11a73e2e27c88aefa72c3a6e9c193d27eab436c4d9d6531cd47 +LibUV.v2.0.1+2.x86_64-unknown-freebsd.tar.gz/md5/951d9da43208d2c48eb00c7ce300b4cf +LibUV.v2.0.1+2.x86_64-unknown-freebsd.tar.gz/sha512/87e578f6cf34c9cc1c965f4958048967740b4ab530836aff33b3339c0d927beccf1f0c58f7e256c9ba98bf1fa0362186a24fcc5bb79ae1f149f86183b4b7f5c1 +LibUV.v2.0.1+2.x86_64-w64-mingw32.tar.gz/md5/4e9c2f078ed7b617a1aa447e1c44abbf +LibUV.v2.0.1+2.x86_64-w64-mingw32.tar.gz/sha512/b3b14c5d447cd742cade43b56bf3867d530dd391c105ddbd7f2b9e0e26ee6a1f3e6fa11148a9ba1540fa598b155da3e56d369a96273a5ea1343b5c3cd4821953 diff --git a/deps/libuv.version b/deps/libuv.version index 045f329a0c9f3..339cba4441875 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -1,2 +1,2 @@ -LIBUV_BRANCH=julia-uv2-1.42.0 -LIBUV_SHA1=c6869fba163a1e04af64ede438a8fd0191e75e9e +LIBUV_BRANCH=julia-uv2-1.39.0 +LIBUV_SHA1=fb3e3364c33ae48c827f6b103e05c3f0e78b79a9 diff --git a/stdlib/LibUV_jll/Project.toml b/stdlib/LibUV_jll/Project.toml index 6a5e2c8ca891b..241a2a16edb61 100644 --- a/stdlib/LibUV_jll/Project.toml +++ b/stdlib/LibUV_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibUV_jll" uuid = "183b4373-6708-53ba-ad28-60e28bb38547" -version = "2.0.1+3" +version = "2.0.1+2" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From 68bdee375a9651770fe10236cbb8232a6e5e6cb7 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Fri, 6 Aug 2021 16:26:42 -0700 Subject: [PATCH 2/2] Revert "add stream shutdown and support half-duplex operation (#40783)" (#41808) This reverts commit 6c4f2165619449182693061e07654b399428e0cf. --- NEWS.md | 1 - base/coreio.jl | 1 - base/exports.jl | 1 - base/io.jl | 124 ++++++++----------- base/iobuffer.jl | 6 - base/libuv.jl | 1 - base/process.jl | 1 - base/stream.jl | 132 ++++++--------------- doc/src/base/io-network.md | 1 - stdlib/Distributed/src/process_messages.jl | 4 +- stdlib/Sockets/src/Sockets.jl | 15 ++- stdlib/Sockets/test/runtests.jl | 35 +----- test/iobuffer.jl | 21 ++-- test/spawn.jl | 8 -- 14 files changed, 111 insertions(+), 240 deletions(-) diff --git a/NEWS.md b/NEWS.md index cb298402ea88d..664bcbd2746fc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -45,7 +45,6 @@ Standard library changes overflow in most cases. The new function `checked_length` is now available, which will try to use checked arithmetic to error if the result may be wrapping. Or use a package such as SaferIntegers.jl when constructing the range. ([#40382]) -* TCP socket objects now expose `shutdown` functionality and support half-open mode usage ([#40783]). #### InteractiveUtils * A new macro `@time_imports` for reporting any time spent importing packages and their dependencies ([#41612]) diff --git a/base/coreio.jl b/base/coreio.jl index d0f8df290b41b..9ef717383dedd 100644 --- a/base/coreio.jl +++ b/base/coreio.jl @@ -13,7 +13,6 @@ write(::DevNull, ::UInt8) = 1 unsafe_write(::DevNull, ::Ptr{UInt8}, n::UInt)::Int = n close(::DevNull) = nothing wait_close(::DevNull) = wait() -bytesavailable(io::DevNull) = 0 let CoreIO = Union{Core.CoreSTDOUT, Core.CoreSTDERR} global write(io::CoreIO, x::UInt8) = Core.write(io, x) diff --git a/base/exports.jl b/base/exports.jl index da0019ab46987..0a8e473055b4b 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -803,7 +803,6 @@ export # I/O and events close, - shutdown, countlines, eachline, readeach, diff --git a/base/io.jl b/base/io.jl index 2eface1ca9458..30a87aa9e1cf3 100644 --- a/base/io.jl +++ b/base/io.jl @@ -60,49 +60,9 @@ function isopen end Close an I/O stream. Performs a [`flush`](@ref) first. """ function close end - -""" - shutdown(stream) - -Shutdown the write half of a full-duplex I/O stream. Performs a [`flush`](@ref) -first. Notify the other end that no more data will be written to the underlying -file. This is not supported by all IO types. - -# Examples -```jldoctest -julia> io = Base.BufferStream(); # this never blocks, so we can read and write on the same Task - -julia> write(io, "request"); - -julia> # calling `read(io)` here would block forever - -julia> shutdown(io); - -julia> read(io, String) -"request" -""" -function shutdown end - -""" - flush(stream) - -Commit all currently buffered writes to the given stream. -""" function flush end - -""" - bytesavailable(io) - -Return the number of bytes available for reading before a read from this stream or buffer will block. - -# Examples -```jldoctest -julia> io = IOBuffer("JuliaLang is a GitHub organization"); - -julia> bytesavailable(io) -34 -``` -""" +function wait_readnb end +function wait_close end function bytesavailable end """ @@ -121,7 +81,7 @@ function readavailable end """ isreadable(io) -> Bool -Return `false` if the specified IO object is not readable. +Return `true` if the specified IO object is readable (if that can be determined). # Examples ```jldoctest @@ -139,12 +99,12 @@ true julia> rm("myfile.txt") ``` """ -isreadable(io::IO) = isopen(io) +function isreadable end """ iswritable(io) -> Bool -Return `false` if the specified IO object is not writable. +Return `true` if the specified IO object is writable (if that can be determined). # Examples ```jldoctest @@ -162,22 +122,9 @@ false julia> rm("myfile.txt") ``` """ -iswritable(io::IO) = isopen(io) - -""" - eof(stream) -> Bool - -Test whether an I/O stream is at end-of-file. If the stream is not yet exhausted, this -function will block to wait for more data if necessary, and then return `false`. Therefore -it is always safe to read one byte after seeing `eof` return `false`. `eof` will return -`false` as long as buffered data is still available, even if the remote end of a connection -is closed. -""" -function eof end - +function iswritable end function copy end -function wait_readnb end -function wait_close end +function eof end """ read(io::IO, T) @@ -410,37 +357,65 @@ end function pipe_reader end function pipe_writer end -for f in (:flush, :shutdown, :iswritable) - @eval $(f)(io::AbstractPipe) = $(f)(pipe_writer(io)::IO) -end write(io::AbstractPipe, byte::UInt8) = write(pipe_writer(io)::IO, byte) write(to::IO, from::AbstractPipe) = write(to, pipe_reader(from)) unsafe_write(io::AbstractPipe, p::Ptr{UInt8}, nb::UInt) = unsafe_write(pipe_writer(io)::IO, p, nb)::Union{Int,UInt} buffer_writes(io::AbstractPipe, args...) = buffer_writes(pipe_writer(io)::IO, args...) +flush(io::AbstractPipe) = flush(pipe_writer(io)::IO) -for f in ( - # peek/mark interface - :mark, :unmark, :reset, :ismarked, - # Simple reader functions - :read, :readavailable, :bytesavailable, :reseteof, :isreadable) - @eval $(f)(io::AbstractPipe) = $(f)(pipe_reader(io)::IO) -end read(io::AbstractPipe, byte::Type{UInt8}) = read(pipe_reader(io)::IO, byte)::UInt8 unsafe_read(io::AbstractPipe, p::Ptr{UInt8}, nb::UInt) = unsafe_read(pipe_reader(io)::IO, p, nb) +read(io::AbstractPipe) = read(pipe_reader(io)::IO) readuntil(io::AbstractPipe, arg::UInt8; kw...) = readuntil(pipe_reader(io)::IO, arg; kw...) readuntil(io::AbstractPipe, arg::AbstractChar; kw...) = readuntil(pipe_reader(io)::IO, arg; kw...) readuntil(io::AbstractPipe, arg::AbstractString; kw...) = readuntil(pipe_reader(io)::IO, arg; kw...) readuntil(io::AbstractPipe, arg::AbstractVector; kw...) = readuntil(pipe_reader(io)::IO, arg; kw...) readuntil_vector!(io::AbstractPipe, target::AbstractVector, keep::Bool, out) = readuntil_vector!(pipe_reader(io)::IO, target, keep, out) readbytes!(io::AbstractPipe, target::AbstractVector{UInt8}, n=length(target)) = readbytes!(pipe_reader(io)::IO, target, n) + +for f in ( + # peek/mark interface + :mark, :unmark, :reset, :ismarked, + # Simple reader functions + :readavailable, :isreadable) + @eval $(f)(io::AbstractPipe) = $(f)(pipe_reader(io)::IO) +end peek(io::AbstractPipe, ::Type{T}) where {T} = peek(pipe_reader(io)::IO, T)::T -wait_readnb(io::AbstractPipe, nb::Int) = wait_readnb(pipe_reader(io)::IO, nb) -eof(io::AbstractPipe) = eof(pipe_reader(io)::IO)::Bool +iswritable(io::AbstractPipe) = iswritable(pipe_writer(io)::IO) isopen(io::AbstractPipe) = isopen(pipe_writer(io)::IO) || isopen(pipe_reader(io)::IO) close(io::AbstractPipe) = (close(pipe_writer(io)::IO); close(pipe_reader(io)::IO)) +wait_readnb(io::AbstractPipe, nb::Int) = wait_readnb(pipe_reader(io)::IO, nb) wait_close(io::AbstractPipe) = (wait_close(pipe_writer(io)::IO); wait_close(pipe_reader(io)::IO)) +""" + bytesavailable(io) + +Return the number of bytes available for reading before a read from this stream or buffer will block. + +# Examples +```jldoctest +julia> io = IOBuffer("JuliaLang is a GitHub organization"); + +julia> bytesavailable(io) +34 +``` +""" +bytesavailable(io::AbstractPipe) = bytesavailable(pipe_reader(io)::IO) +bytesavailable(io::DevNull) = 0 + +""" + eof(stream) -> Bool + +Test whether an I/O stream is at end-of-file. If the stream is not yet exhausted, this +function will block to wait for more data if necessary, and then return `false`. Therefore +it is always safe to read one byte after seeing `eof` return `false`. `eof` will return +`false` as long as buffered data is still available, even if the remote end of a connection +is closed. +""" +eof(io::AbstractPipe) = eof(pipe_reader(io)::IO)::Bool +reseteof(io::AbstractPipe) = reseteof(pipe_reader(io)::IO) + # Exception-safe wrappers (io = open(); try f(io) finally close(io)) @@ -1144,6 +1119,11 @@ ismarked(io::IO) = io.mark >= 0 # Make sure all IO streams support flush, even if only as a no-op, # to make it easier to write generic I/O code. +""" + flush(stream) + +Commit all currently buffered writes to the given stream. +""" flush(io::IO) = nothing """ diff --git a/base/iobuffer.jl b/base/iobuffer.jl index f65ed3f894fe0..e204eca906cbf 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -334,12 +334,6 @@ end eof(io::GenericIOBuffer) = (io.ptr-1 == io.size) -function shutdown(io::GenericIOBuffer) - io.writable = false - # OR throw(_UVError("shutdown", UV_ENOTSOCK)) - nothing -end - @noinline function close(io::GenericIOBuffer{T}) where T io.readable = false io.writable = false diff --git a/base/libuv.jl b/base/libuv.jl index c64cbff564b66..c63045f4b1b68 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -107,7 +107,6 @@ end function uv_alloc_buf end function uv_readcb end function uv_writecb_task end -function uv_shutdowncb_task end function uv_return_spawn end function uv_asynccb end function uv_timercb end diff --git a/base/process.jl b/base/process.jl index 6be7099f94f35..b3ec79fa1ab4e 100644 --- a/base/process.jl +++ b/base/process.jl @@ -275,7 +275,6 @@ function setup_stdio(stdio::Union{IOBuffer, BufferStream}, child_readable::Bool) @warn "Process error" exception=(ex, catch_backtrace()) finally close(parent) - child_readable || shutdown(stdio) end end catch ex diff --git a/base/stream.jl b/base/stream.jl index 6e433b771f0d2..6cbd1d3b86a28 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -109,7 +109,7 @@ function eof(s::LibuvStream) # and that we won't return true if there's a readerror pending (it'll instead get thrown). # This requires some careful ordering here (TODO: atomic loads) bytesavailable(s) > 0 && return false - open = isreadable(s) # must precede readerror check + open = isopen(s) # must precede readerror check s.readerror === nothing || throw(s.readerror) return !open end @@ -270,7 +270,6 @@ show(io::IO, stream::LibuvStream) = print(io, typeof(stream), "(", function isreadable(io::LibuvStream) bytesavailable(io) > 0 && return true isopen(io) || return false - io.status == StatusEOF && return false return ccall(:uv_is_readable, Cint, (Ptr{Cvoid},), io.handle) != 0 end @@ -379,7 +378,7 @@ function isopen(x::Union{LibuvStream, LibuvServer}) if x.status == StatusUninit || x.status == StatusInit throw(ArgumentError("$x is not initialized")) end - return x.status != StatusClosed + return x.status != StatusClosed && x.status != StatusEOF end function check_open(x::Union{LibuvStream, LibuvServer}) @@ -391,13 +390,13 @@ end function wait_readnb(x::LibuvStream, nb::Int) # fast path before iolock acquire bytesavailable(x.buffer) >= nb && return - open = isopen(x) && x.status != StatusEOF # must precede readerror check + open = isopen(x) # must precede readerror check x.readerror === nothing || throw(x.readerror) open || return iolock_begin() # repeat fast path after iolock acquire, before other expensive work bytesavailable(x.buffer) >= nb && (iolock_end(); return) - open = isopen(x) && x.status != StatusEOF + open = isopen(x) x.readerror === nothing || throw(x.readerror) open || (iolock_end(); return) # now do the "real" work @@ -408,7 +407,6 @@ function wait_readnb(x::LibuvStream, nb::Int) while bytesavailable(x.buffer) < nb x.readerror === nothing || throw(x.readerror) isopen(x) || break - x.status != StatusEOF || break x.throttle = max(nb, x.throttle) start_reading(x) # ensure we are reading iolock_end() @@ -433,50 +431,6 @@ function wait_readnb(x::LibuvStream, nb::Int) nothing end -function shutdown(s::LibuvStream) - iolock_begin() - check_open(s) - req = Libc.malloc(_sizeof_uv_shutdown) - uv_req_set_data(req, C_NULL) # in case we get interrupted before arriving at the wait call - err = ccall(:uv_shutdown, Int32, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), - req, s, @cfunction(uv_shutdowncb_task, Cvoid, (Ptr{Cvoid}, Cint))) - if err < 0 - Libc.free(req) - uv_error("shutdown", err) - end - ct = current_task() - preserve_handle(ct) - sigatomic_begin() - uv_req_set_data(req, ct) - iolock_end() - status = try - sigatomic_end() - wait()::Cint - finally - # try-finally unwinds the sigatomic level, so need to repeat sigatomic_end - sigatomic_end() - iolock_begin() - ct.queue === nothing || list_deletefirst!(ct.queue, ct) - if uv_req_data(req) != C_NULL - # req is still alive, - # so make sure we won't get spurious notifications later - uv_req_set_data(req, C_NULL) - else - # done with req - Libc.free(req) - end - iolock_end() - unpreserve_handle(ct) - if isopen(s) && (s.status == StatusEOF && !isa(s, TTY)) || ccall(:uv_is_readable, Cint, (Ptr{Cvoid},), s.handle) == 0 - close(s) - end - end - if status < 0 - throw(_UVError("shutdown", status)) - end - nothing -end - function wait_close(x::Union{LibuvStream, LibuvServer}) preserve_handle(x) lock(x.cond) @@ -497,7 +451,7 @@ function close(stream::Union{LibuvStream, LibuvServer}) if stream.status == StatusInit ccall(:jl_forceclose_uv, Cvoid, (Ptr{Cvoid},), stream.handle) stream.status = StatusClosing - elseif isopen(stream) + elseif isopen(stream) || stream.status == StatusEOF should_wait = uv_handle_data(stream) != C_NULL if stream.status != StatusClosing ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle) @@ -652,33 +606,35 @@ function uv_readcb(handle::Ptr{Cvoid}, nread::Cssize_t, buf::Ptr{Cvoid}) nrequested = ccall(:jl_uv_buf_len, Csize_t, (Ptr{Cvoid},), buf) function readcb_specialized(stream::LibuvStream, nread::Int, nrequested::UInt) lock(stream.cond) - if nread < 0 - if nread == UV_ENOBUFS && nrequested == 0 - # remind the client that stream.buffer is full - notify(stream.cond) - elseif nread == UV_EOF # libuv called uv_stop_reading already - if stream.status != StatusClosing - if stream isa TTY || ccall(:uv_is_writable, Cint, (Ptr{Cvoid},), stream.handle) != 0 - # stream can still be used either by reseteof or write - stream.status = StatusEOF + try + if nread < 0 + if nread == UV_ENOBUFS && nrequested == 0 + # remind the client that stream.buffer is full + notify(stream.cond) + elseif nread == UV_EOF + if isa(stream, TTY) + stream.status = StatusEOF # libuv called uv_stop_reading already notify(stream.cond) - else - # underlying stream is no longer useful: begin finalization + elseif stream.status != StatusClosing + # begin shutdown of the stream ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle) stream.status = StatusClosing end + else + stream.readerror = _UVError("read", nread) + # This is a fatal connection error. Shutdown requests as per the usual + # close function won't work and libuv will fail with an assertion failure + ccall(:jl_forceclose_uv, Cvoid, (Ptr{Cvoid},), stream) + stream.status = StatusClosing + notify(stream.cond) end else - stream.readerror = _UVError("read", nread) - # This is a fatal connection error - ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle) - stream.status = StatusClosing + notify_filled(stream.buffer, nread) + notify(stream.cond) end - else - notify_filled(stream.buffer, nread) - notify(stream.cond) + finally + unlock(stream.cond) end - unlock(stream.cond) # Stop background reading when # 1) there's nobody paying attention to the data we are reading @@ -695,7 +651,6 @@ function uv_readcb(handle::Ptr{Cvoid}, nread::Cssize_t, buf::Ptr{Cvoid}) nothing end readcb_specialized(stream_unknown_type, Int(nread), UInt(nrequested)) - nothing end function reseteof(x::TTY) @@ -889,7 +844,6 @@ function readbytes!(s::LibuvStream, a::Vector{UInt8}, nb::Int) while bytesavailable(buf) < nb s.readerror === nothing || throw(s.readerror) isopen(s) || break - s.status != StatusEOF || break iolock_end() wait_readnb(s, nb) iolock_begin() @@ -936,7 +890,6 @@ function unsafe_read(s::LibuvStream, p::Ptr{UInt8}, nb::UInt) while bytesavailable(buf) < nb s.readerror === nothing || throw(s.readerror) isopen(s) || throw(EOFError()) - s.status != StatusEOF || throw(EOFError()) iolock_end() wait_readnb(s, nb) iolock_begin() @@ -993,14 +946,13 @@ function readuntil(x::LibuvStream, c::UInt8; keep::Bool=false) @assert buf.seekable == false if !occursin(c, buf) # fast path checks first x.readerror === nothing || throw(x.readerror) - if isopen(x) && x.status != StatusEOF + if isopen(x) preserve_handle(x) lock(x.cond) try while !occursin(c, x.buffer) x.readerror === nothing || throw(x.readerror) isopen(x) || break - x.status != StatusEOF || break start_reading(x) # ensure we are reading iolock_end() wait(x.cond) @@ -1163,20 +1115,6 @@ function uv_writecb_task(req::Ptr{Cvoid}, status::Cint) nothing end -function uv_shutdowncb_task(req::Ptr{Cvoid}, status::Cint) - d = uv_req_data(req) - if d != C_NULL - uv_req_set_data(req, C_NULL) # let the Task know we got the shutdowncb - t = unsafe_pointer_to_objref(d)::Task - schedule(t, status) - else - # no owner for this req, safe to just free it - Libc.free(req) - end - nothing -end - - _fd(x::IOStream) = RawFD(fd(x)) _fd(x::Union{OS_HANDLE, RawFD}) = x @@ -1467,20 +1405,18 @@ mutable struct BufferStream <: LibuvStream buffer::IOBuffer cond::Threads.Condition readerror::Any + is_open::Bool buffer_writes::Bool lock::ReentrantLock # advisory lock - status::Int - BufferStream() = new(PipeBuffer(), Threads.Condition(), nothing, false, ReentrantLock(), StatusActive) + BufferStream() = new(PipeBuffer(), Threads.Condition(), nothing, true, false, ReentrantLock()) end -isopen(s::BufferStream) = s.status != StatusClosed - -shutdown(s::BufferStream) = close(s) +isopen(s::BufferStream) = s.is_open function close(s::BufferStream) lock(s.cond) do - s.status = StatusClosed + s.is_open = false notify(s.cond) nothing end @@ -1503,8 +1439,8 @@ function unsafe_read(s::BufferStream, a::Ptr{UInt8}, nb::UInt) end bytesavailable(s::BufferStream) = bytesavailable(s.buffer) -isreadable(s::BufferStream) = (isopen(s) || bytesavailable(s) > 0) && s.buffer.readable -iswritable(s::BufferStream) = isopen(s) && s.buffer.writable +isreadable(s::BufferStream) = s.buffer.readable +iswritable(s::BufferStream) = s.buffer.writable function wait_readnb(s::BufferStream, nb::Int) lock(s.cond) do @@ -1514,7 +1450,7 @@ function wait_readnb(s::BufferStream, nb::Int) end end -show(io::IO, s::BufferStream) = print(io, "BufferStream(bytes waiting=", bytesavailable(s.buffer), ", isopen=", isopen(s), ")") +show(io::IO, s::BufferStream) = print(io, "BufferStream() bytes waiting:", bytesavailable(s.buffer), ", isopen:", s.is_open) function readuntil(s::BufferStream, c::UInt8; keep::Bool=false) bytes = lock(s.cond) do diff --git a/doc/src/base/io-network.md b/doc/src/base/io-network.md index 8b2ea3c4c2412..2d6a462400813 100644 --- a/doc/src/base/io-network.md +++ b/doc/src/base/io-network.md @@ -13,7 +13,6 @@ Base.take!(::Base.GenericIOBuffer) Base.fdio Base.flush Base.close -Base.shutdown Base.write Base.read Base.read! diff --git a/stdlib/Distributed/src/process_messages.jl b/stdlib/Distributed/src/process_messages.jl index 732b972858dc9..8d5dac5af571e 100644 --- a/stdlib/Distributed/src/process_messages.jl +++ b/stdlib/Distributed/src/process_messages.jl @@ -230,8 +230,8 @@ function message_handler_loop(r_stream::IO, w_stream::IO, incoming::Bool) deregister_worker(wpid) end - close(r_stream) - close(w_stream) + isopen(r_stream) && close(r_stream) + isopen(w_stream) && close(w_stream) if (myid() == 1) && (wpid > 1) if oldstate != W_TERMINATING diff --git a/stdlib/Sockets/src/Sockets.jl b/stdlib/Sockets/src/Sockets.jl index fb46b9255e6f0..6952aa9bd8a0f 100644 --- a/stdlib/Sockets/src/Sockets.jl +++ b/stdlib/Sockets/src/Sockets.jl @@ -139,6 +139,9 @@ function TCPServer(; delay=true) return tcp end +isreadable(io::TCPSocket) = isopen(io) || bytesavailable(io) > 0 +iswritable(io::TCPSocket) = isopen(io) && io.status != StatusClosing + """ accept(server[, client]) @@ -575,11 +578,11 @@ Enables or disables Nagle's algorithm on a given TCP server or socket. """ function nagle(sock::Union{TCPServer, TCPSocket}, enable::Bool) # disable or enable Nagle's algorithm on all OSes - iolock_begin() - check_open(sock) + Sockets.iolock_begin() + Sockets.check_open(sock) err = ccall(:uv_tcp_nodelay, Cint, (Ptr{Cvoid}, Cint), sock.handle, Cint(!enable)) # TODO: check err - iolock_end() + Sockets.iolock_end() return err end @@ -589,15 +592,15 @@ end On Linux systems, the TCP_QUICKACK is disabled or enabled on `socket`. """ function quickack(sock::Union{TCPServer, TCPSocket}, enable::Bool) - iolock_begin() - check_open(sock) + Sockets.iolock_begin() + Sockets.check_open(sock) @static if Sys.islinux() # tcp_quickack is a linux only option if ccall(:jl_tcp_quickack, Cint, (Ptr{Cvoid}, Cint), sock.handle, Cint(enable)) < 0 @warn "Networking unoptimized ( Error enabling TCP_QUICKACK : $(Libc.strerror(Libc.errno())) )" maxlog=1 end end - iolock_end() + Sockets.iolock_end() nothing end diff --git a/stdlib/Sockets/test/runtests.jl b/stdlib/Sockets/test/runtests.jl index 328ea929f4b4b..5ac88b7216bef 100644 --- a/stdlib/Sockets/test/runtests.jl +++ b/stdlib/Sockets/test/runtests.jl @@ -551,42 +551,17 @@ end r = @async close(s) @test_throws Base._UVError("connect", Base.UV_ECANCELED) Sockets.wait_connected(s) fetch(r) - close(srv) end end @testset "iswritable" begin let addr = Sockets.InetAddr(ip"127.0.0.1", 4445) srv = listen(addr) - let s = Sockets.TCPSocket() - Sockets.connect!(s, addr) - @test iswritable(s) broken=Sys.iswindows() - close(s) - @test !iswritable(s) - end - let s = Sockets.connect(addr) - @test iswritable(s) - shutdown(s) - @test !iswritable(s) - close(s) - end - close(srv) - srv = listen(addr) - let s = Sockets.connect(addr) - let c = accept(srv) - Base.errormonitor(@async try; write(c, c); finally; close(c); end) - end - @test iswritable(s) - write(s, "hello world\n") - shutdown(s) - @test !iswritable(s) - @test isreadable(s) - @test read(s, String) == "hello world\n" - @test !isreadable(s) - @test !isopen(s) - close(s) - end - close(srv) + s = Sockets.TCPSocket() + Sockets.connect!(s, addr) + @test iswritable(s) + close(s) + @test !iswritable(s) end end diff --git a/test/iobuffer.jl b/test/iobuffer.jl index 5514b6dc03f7f..80972a7c65448 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -9,7 +9,7 @@ bufcontents(io::Base.GenericIOBuffer) = unsafe_string(pointer(io.data), io.size) @testset "Read/write empty IOBuffer" begin io = IOBuffer() @test eof(io) - @test_throws EOFError read(io, UInt8) + @test_throws EOFError read(io,UInt8) @test write(io,"abc") === 3 @test isreadable(io) @test iswritable(io) @@ -18,7 +18,7 @@ bufcontents(io::Base.GenericIOBuffer) = unsafe_string(pointer(io.data), io.size) @test position(io) == 3 @test eof(io) seek(io, 0) - @test read(io, UInt8) == convert(UInt8, 'a') + @test read(io,UInt8) == convert(UInt8, 'a') a = Vector{UInt8}(undef, 2) @test read!(io, a) == a @test a == UInt8['b','c'] @@ -34,24 +34,22 @@ bufcontents(io::Base.GenericIOBuffer) = unsafe_string(pointer(io.data), io.size) truncate(io, 10) @test position(io) == 0 @test all(io.data .== 0) - @test write(io, Int16[1, 2, 3, 4, 5, 6]) === 12 + @test write(io,Int16[1,2,3,4,5,6]) === 12 seek(io, 2) truncate(io, 10) @test ioslength(io) == 10 io.readable = false - @test_throws ArgumentError read!(io, UInt8[0]) + @test_throws ArgumentError read!(io,UInt8[0]) truncate(io, 0) @test write(io,"boston\ncambridge\n") > 0 @test String(take!(io)) == "boston\ncambridge\n" @test String(take!(io)) == "" @test write(io, ComplexF64(0)) === 16 @test write(io, Rational{Int64}(1//2)) === 16 - @test shutdown(io) === nothing - @test_throws ArgumentError write(io, UInt8[0]) + close(io) + @test_throws ArgumentError write(io,UInt8[0]) + @test_throws ArgumentError seek(io,0) @test eof(io) - @test close(io) === nothing - @test_throws ArgumentError write(io, UInt8[0]) - @test_throws ArgumentError seek(io, 0) end @testset "Read/write readonly IOBuffer" begin @@ -239,7 +237,7 @@ end @test isreadable(bstream) @test iswritable(bstream) @test bytesavailable(bstream) == 0 - @test sprint(show, bstream) == "BufferStream(bytes waiting=$(bytesavailable(bstream.buffer)), isopen=true)" + @test sprint(show, bstream) == "BufferStream() bytes waiting:$(bytesavailable(bstream.buffer)), isopen:true" a = rand(UInt8,10) write(bstream,a) @test !eof(bstream) @@ -253,10 +251,9 @@ end @test !eof(bstream) read!(bstream,c) @test c == a[3:10] - @test shutdown(bstream) === nothing + @test close(bstream) === nothing @test eof(bstream) @test bytesavailable(bstream) == 0 - @test close(bstream) === nothing flag = Ref{Bool}(false) event = Base.Event() bstream = Base.BufferStream() diff --git a/test/spawn.jl b/test/spawn.jl index 9ec7c6842bedb..95915a5ad804b 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -765,15 +765,7 @@ let text = "input-test-text" @test read(proc, String) == string(length(text), '\n') @test success(proc) @test String(take!(b)) == text - - out = Base.BufferStream() - proc = run(catcmd, IOBuffer(text), out, wait=false) - @test proc.out === out - @test read(out, String) == text - @test success(proc) end - - @test repr(Base.CmdRedirect(``, devnull, 0, false)) == "pipeline(``, stdin>Base.DevNull())" @test repr(Base.CmdRedirect(``, devnull, 1, true)) == "pipeline(``, stdout