Skip to content

Backports for Julia 1.8.2 #46663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d174fd4
docs: print extra information when deploying (#46030)
mortenpi Jul 14, 2022
f21aea0
Improve type stability of `platforms_match(::AbstractPlatform, ::Abst…
ranocha Aug 31, 2022
89facae
Improve inference in REPL LineEdit.jl `getEntry` (#46550)
ranocha Aug 31, 2022
53a7c00
Improve inferrability of `open(f, cmd, ...)` (#46551)
ranocha Aug 31, 2022
056e260
Deploy release-* branch docs too (#46618)
mortenpi Sep 5, 2022
3761fd3
add warning for function declaration with undefined static parameter …
vtjnash Sep 6, 2022
e0a820e
avoid inferring when compilation signature differs from call site sig…
vtjnash Sep 2, 2022
16a7aac
For Julia 1.8.x, `Tar` should track the `release-1.10` branch of the …
DilumAluthge Sep 13, 2022
9f2d553
inference: concretize `invoke` callsite correctly (#46743)
aviatesk Sep 14, 2022
6e4cf29
Remove contradictory inline annotations (#46767)
oscardssmith Sep 15, 2022
a233e3e
bump the Tar stdlib from 0f8a73d to c9e7185 for Julia 1.8 (#46758)
ranocha Sep 15, 2022
237c92d
Improve dispatch of `findall(testf::F, A::AbstractArray)` (#46553)
ranocha Sep 6, 2022
3fa8073
fix issue #46665, `prod(::Array{BigInt})` (#46667)
rfourquet Sep 7, 2022
2aaded9
fix invalidations from loading ArrayInterface.jl (#46673)
ranocha Sep 11, 2022
3d8b92f
improve type stability of `lt(p::Perm, a::Integer, b::Integer)` (#46732)
ranocha Sep 13, 2022
9d593ce
improve type stability of `process_overrides(artifact_dict::Dict, pkk…
ranocha Sep 14, 2022
85ecb8e
fix invalidations from loading Static.jl (#46761)
ranocha Sep 15, 2022
02af18b
improvements to constant values in IR (#45173)
JeffBezanson Aug 17, 2022
22d1000
LibGit2: correct regex for credential helpers (#46597)
barucden Sep 6, 2022
ab67e93
improve type stability of `tail/front(::NamedTuple)` (#46762)
ranocha Sep 15, 2022
7955e8a
Also merge var with unchanged bounds. (#46757)
N5N3 Sep 15, 2022
83f2ae8
CI (`Create Buildbot Statuses`): remove `tester_macos64` from the lis…
DilumAluthge Apr 9, 2022
b1e7cac
CI (`Create Buildbot Statuses`): remove `tester_linux32` from the lis…
DilumAluthge Apr 21, 2022
b69fa6a
doc: guard release branch regex with ^...$ (#46647)
mortenpi Sep 16, 2022
b6883b0
Fix `mapreduce` on `AdjOrTrans` (#46605)
SobhanMP Sep 16, 2022
cc2b7c5
Make the "system image too large" error message more descriptive (#46…
DilumAluthge Sep 16, 2022
d336126
Support LibGit2 ABI for 1.4.0 and later
fxcoudert Sep 16, 2022
80fda11
tcp: re-enable half-duplex operation support (#46088)
vtjnash Jul 25, 2022
86d0354
libuv: bump version to v2-1.44.2 (#46086)
vtjnash Aug 5, 2022
b79226e
inference: make `limit::Int` as a caching key of `CachedMethodTable` …
aviatesk Sep 17, 2022
5b365e5
Fix a bug accidentally introduced by 43453 (#46816)
kpamnany Sep 17, 2022
6bfa51f
Expose constrained memory limits and have the GC use them (#46796)
maleadt Sep 20, 2022
39ae07c
set number of openblas threads to 1 while precompiling (#46792)
KristofferC Sep 20, 2022
285b75c
update to latest Pkg 1.8
Sep 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/statuses.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ jobs:
- run: |
declare -a CONTEXT_LIST=(
"buildbot/tester_freebsd64"
"buildbot/tester_macos64"
"buildbot/tester_win32"
"buildbot/tester_win64"
)
Expand Down
2 changes: 1 addition & 1 deletion base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2308,7 +2308,7 @@ findall(testf::Function, A) = collect(first(p) for p in pairs(A) if testf(last(p

# Broadcasting is much faster for small testf, and computing
# integer indices from logical index using findall has a negligible cost
findall(testf::Function, A::AbstractArray) = findall(testf.(A))
findall(testf::F, A::AbstractArray) where {F<:Function} = findall(testf.(A))

"""
findall(A)
Expand Down
2 changes: 1 addition & 1 deletion base/binaryplatforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,7 @@ function platforms_match(a::AbstractPlatform, b::AbstractPlatform)

# Call the comparator, passing in which objects requested this comparison (one, the other, or both)
# For some comparators this doesn't matter, but for non-symmetrical comparisons, it does.
if !comparator(ak, bk, a_comp == comparator, b_comp == comparator)
if !(comparator(ak, bk, a_comp == comparator, b_comp == comparator)::Bool)
return false
end
end
Expand Down
72 changes: 46 additions & 26 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
result = abstract_call_method(interp, method, sig_n, svec(), multiple_matches, sv)
rt = result.rt
edge = result.edge
edge !== nothing && push!(edges, edge)
edge === nothing || push!(edges, edge)
this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i]
this_arginfo = ArgInfo(fargs, this_argtypes)
const_call_result = abstract_call_method_with_const_args(interp, result,
Expand All @@ -136,25 +136,11 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
this_conditional = ignorelimited(this_rt)
this_rt = widenwrappedconditional(this_rt)
else
if infer_compilation_signature(interp)
# Also infer the compilation signature for this method, so it's available
# to the compiler in case it ends up needing it (which is likely).
csig = get_compileable_sig(method, sig, match.sparams)
if csig !== nothing && csig !== sig
# The result of this inference is not directly used, so temporarily empty
# the use set for the current SSA value.
saved_uses = sv.ssavalue_uses[sv.currpc]
sv.ssavalue_uses[sv.currpc] = empty_bitset
abstract_call_method(interp, method, csig, match.sparams, multiple_matches, sv)
sv.ssavalue_uses[sv.currpc] = saved_uses
end
end

result = abstract_call_method(interp, method, sig, match.sparams, multiple_matches, sv)
this_conditional = ignorelimited(result.rt)
this_rt = widenwrappedconditional(result.rt)
edge = result.edge
edge !== nothing && push!(edges, edge)
edge === nothing || push!(edges, edge)
# try constant propagation with argtypes for this match
# this is in preparation for inlining, or improving the return result
this_argtypes = isa(matches, MethodMatches) ? argtypes : matches.applicable_argtypes[i]
Expand Down Expand Up @@ -214,6 +200,26 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),

rettype = from_interprocedural!(rettype, sv, arginfo, conditionals)

# Also considering inferring the compilation signature for this method, so
# it is available to the compiler in case it ends up needing it.
if infer_compilation_signature(interp) && 1 == seen == napplicable && rettype !== Any && rettype !== Union{} && !is_removable_if_unused(all_effects)
match = applicable[1]::MethodMatch
method = match.method
sig = match.spec_types
mi = specialize_method(match; preexisting=true)
if mi !== nothing && !const_prop_methodinstance_heuristic(interp, match, mi::MethodInstance, arginfo, sv)
csig = get_compileable_sig(method, sig, match.sparams)
if csig !== nothing && csig !== sig
# The result of this inference is not directly used, so temporarily empty
# the use set for the current SSA value.
saved_uses = sv.ssavalue_uses[sv.currpc]
sv.ssavalue_uses[sv.currpc] = empty_bitset
abstract_call_method(interp, method, csig, match.sparams, multiple_matches, sv)
sv.ssavalue_uses[sv.currpc] = saved_uses
end
end
end

if call_result_unused(sv) && !(rettype === Bottom)
add_remark!(interp, sv, "Call result type was widened because the return value is unused")
# We're mainly only here because the optimizer might want this code,
Expand Down Expand Up @@ -765,13 +771,25 @@ function collect_const_args((; argtypes)::ArgInfo)
isa(a, Const) ? a.val :
isconstType(a) ? (a::DataType).parameters[1] :
(a::DataType).instance
end for i in 2:length(argtypes) ]
end for i = 2:length(argtypes) ]
end

struct InvokeCall
types # ::Type
lookupsig # ::Type
InvokeCall(@nospecialize(types), @nospecialize(lookupsig)) = new(types, lookupsig)
end

function concrete_eval_call(interp::AbstractInterpreter,
@nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState)
@nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState,
invokecall::Union{Nothing,InvokeCall}=nothing)
concrete_eval_eligible(interp, f, result, arginfo, sv) || return nothing
args = collect_const_args(arginfo)
if invokecall !== nothing
# this call should be `invoke`d, rewrite `args` back now
pushfirst!(args, f, invokecall.types)
f = invoke
end
world = get_world_counter(interp)
value = try
Core._call_in_world_total(world, f, args...)
Expand Down Expand Up @@ -811,13 +829,13 @@ struct ConstCallResults
new(rt, const_result, effects)
end

function abstract_call_method_with_const_args(interp::AbstractInterpreter, result::MethodCallResult,
@nospecialize(f), arginfo::ArgInfo, match::MethodMatch,
sv::InferenceState)
function abstract_call_method_with_const_args(interp::AbstractInterpreter,
result::MethodCallResult, @nospecialize(f), arginfo::ArgInfo, match::MethodMatch,
sv::InferenceState, invokecall::Union{Nothing,InvokeCall}=nothing)
if !const_prop_enabled(interp, sv, match)
return nothing
end
val = concrete_eval_call(interp, f, result, arginfo, sv)
val = concrete_eval_call(interp, f, result, arginfo, sv, invokecall)
if val !== nothing
add_backedge!(result.edge, sv)
return val
Expand Down Expand Up @@ -1547,10 +1565,10 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
nargtype isa DataType || return CallMeta(Any, Effects(), false) # other cases are not implemented below
isdispatchelem(ft) || return CallMeta(Any, Effects(), false) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below
ft = ft::DataType
types = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types)::Type
lookupsig = rewrap_unionall(Tuple{ft, unwrap_unionall(types).parameters...}, types)::Type
nargtype = Tuple{ft, nargtype.parameters...}
argtype = Tuple{ft, argtype.parameters...}
match, valid_worlds, overlayed = findsup(types, method_table(interp))
match, valid_worlds, overlayed = findsup(lookupsig, method_table(interp))
match === nothing && return CallMeta(Any, Effects(), false)
update_valid_age!(sv, valid_worlds)
method = match.method
Expand All @@ -1569,8 +1587,10 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
# t, a = ti.parameters[i], argtypes′[i]
# argtypes′[i] = t ⊑ a ? t : a
# end
const_call_result = abstract_call_method_with_const_args(interp, result,
overlayed ? nothing : singleton_type(ft′), arginfo, match, sv)
f = overlayed ? nothing : singleton_type(ft′)
invokecall = InvokeCall(types, lookupsig)
const_call_result = abstract_call_method_with_const_args(interp,
result, f, arginfo, match, sv, invokecall)
const_result = nothing
if const_call_result !== nothing
if const_call_result.rt ⊑ rt
Expand Down
18 changes: 13 additions & 5 deletions base/compiler/methodtable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,23 @@ struct OverlayMethodTable <: MethodTableView
mt::Core.MethodTable
end

struct MethodMatchKey
sig # ::Type
limit::Int
MethodMatchKey(@nospecialize(sig), limit::Int) = new(sig, limit)
end

"""
struct CachedMethodTable <: MethodTableView

Overlays another method table view with an additional local fast path cache that
can respond to repeated, identical queries faster than the original method table.
"""
struct CachedMethodTable{T} <: MethodTableView
cache::IdDict{Any, Union{Missing, MethodMatchResult}}
cache::IdDict{MethodMatchKey, Union{Missing,MethodMatchResult}}
table::T
end
CachedMethodTable(table::T) where T = CachedMethodTable{T}(IdDict{Any, Union{Missing, MethodMatchResult}}(), table)
CachedMethodTable(table::T) where T = CachedMethodTable{T}(IdDict{MethodMatchKey, Union{Missing,MethodMatchResult}}(), table)

"""
findall(sig::Type, view::MethodTableView; limit::Int=typemax(Int)) ->
Expand Down Expand Up @@ -109,9 +115,11 @@ function findall(@nospecialize(sig::Type), table::CachedMethodTable; limit::Int=
# as for concrete types, we cache result at on the next level
return findall(sig, table.table; limit)
end
box = Core.Box(sig)
return get!(table.cache, sig) do
findall(box.contents, table.table; limit)
key = MethodMatchKey(sig, limit)
if haskey(table.cache, key)
return table.cache[key]
else
return table.cache[key] = findall(sig, table.table; limit)
end
end

Expand Down
5 changes: 5 additions & 0 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,11 @@ function inline_invoke!(
return nothing
end

function invoke_signature(invokesig::Vector{Any})
ft, argtyps = widenconst(invokesig[2]), instanceof_tfunc(widenconst(invokesig[3]))[1]
return rewrap_unionall(Tuple{ft, unwrap_unionall(argtyps).parameters...}, argtyps)
end

function narrow_opaque_closure!(ir::IRCode, stmt::Expr, @nospecialize(info), state::InliningState)
if isa(info, OpaqueClosureCreateInfo)
lbt = argextype(stmt.args[2], ir)
Expand Down
8 changes: 6 additions & 2 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -667,8 +667,12 @@ function prod(arr::AbstractArray{BigInt})
# to account for the rounding to limbs in MPZ.mul!
# (BITS_PER_LIMB-1 would typically be enough, to which we add
# 1 for the initial multiplication by init=1 in foldl)
nbits = GC.@preserve arr sum(arr; init=BITS_PER_LIMB) do x
abs(x.size) * BITS_PER_LIMB - leading_zeros(unsafe_load(x.d))
nbits = BITS_PER_LIMB
for x in arr
iszero(x) && return zero(BigInt)
xsize = abs(x.size)
lz = GC.@preserve x leading_zeros(unsafe_load(x.d, xsize))
nbits += xsize * BITS_PER_LIMB - lz
end
init = BigInt(; nbits)
MPZ.set_si!(init, 1)
Expand Down
14 changes: 8 additions & 6 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1587,12 +1587,14 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, concrete_d
deps_eltype = sprint(show, eltype(concrete_deps); context = :module=>nothing)
deps = deps_eltype * "[" * join(deps_strs, ",") * "]"
trace = isassigned(PRECOMPILE_TRACE_COMPILE) ? `--trace-compile=$(PRECOMPILE_TRACE_COMPILE[])` : ``
io = open(pipeline(`$(julia_cmd()::Cmd) -O0
--output-ji $output --output-incremental=yes
--startup-file=no --history-file=no --warn-overwrite=yes
--color=$(have_color === nothing ? "auto" : have_color ? "yes" : "no")
$trace
-`, stderr = internal_stderr, stdout = internal_stdout),
io = open(pipeline(addenv(`$(julia_cmd()::Cmd) -O0
--output-ji $output --output-incremental=yes
--startup-file=no --history-file=no --warn-overwrite=yes
--color=$(have_color === nothing ? "auto" : have_color ? "yes" : "no")
$trace
-`,
"OPENBLAS_NUM_THREADS" => 1),
stderr = internal_stderr, stdout = internal_stdout),
"w", stdout)
# write data over stdin to avoid the (unlikely) case of exceeding max command line size
write(io.in, """
Expand Down
7 changes: 4 additions & 3 deletions base/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ function NamedTuple{names}(nt::NamedTuple) where {names}
types = Tuple{(fieldtype(nt, idx[n]) for n in 1:length(idx))...}
Expr(:new, :(NamedTuple{names, $types}), Any[ :(getfield(nt, $(idx[n]))) for n in 1:length(idx) ]...)
else
types = Tuple{(fieldtype(typeof(nt), names[n]) for n in 1:length(names))...}
length_names = length(names)::Integer
types = Tuple{(fieldtype(typeof(nt), names[n]) for n in 1:length_names)...}
NamedTuple{names, types}(map(Fix1(getfield, nt), names))
end
end
Expand Down Expand Up @@ -318,8 +319,8 @@ values(nt::NamedTuple) = Tuple(nt)
haskey(nt::NamedTuple, key::Union{Integer, Symbol}) = isdefined(nt, key)
get(nt::NamedTuple, key::Union{Integer, Symbol}, default) = haskey(nt, key) ? getfield(nt, key) : default
get(f::Callable, nt::NamedTuple, key::Union{Integer, Symbol}) = haskey(nt, key) ? getfield(nt, key) : f()
tail(t::NamedTuple{names}) where names = NamedTuple{tail(names)}(t)
front(t::NamedTuple{names}) where names = NamedTuple{front(names)}(t)
tail(t::NamedTuple{names}) where names = NamedTuple{tail(names::Tuple)}(t)
front(t::NamedTuple{names}) where names = NamedTuple{front(names::Tuple)}(t)

@pure function diff_names(an::Tuple{Vararg{Symbol}}, bn::Tuple{Vararg{Symbol}})
@nospecialize an bn
Expand Down
2 changes: 1 addition & 1 deletion base/ordering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ lt(o::Lt, a, b) = o.lt(a,b)
@propagate_inbounds function lt(p::Perm, a::Integer, b::Integer)
da = p.data[a]
db = p.data[b]
lt(p.order, da, db) | (!lt(p.order, db, da) & (a < b))
(lt(p.order, da, db)::Bool) | (!(lt(p.order, db, da)::Bool) & (a < b))
end

_ord(lt::typeof(isless), by::typeof(identity), order::Ordering) = order
Expand Down
14 changes: 12 additions & 2 deletions base/permuteddimsarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,21 @@ end
P
end

function Base._mapreduce_dim(f, op, init::Base._InitialValue, A::PermutedDimsArray, dims::Colon)
const CommutativeOps = Union{typeof(+),typeof(Base.add_sum),typeof(min),typeof(max),typeof(Base._extrema_rf),typeof(|),typeof(&)}

function Base._mapreduce_dim(f, op::CommutativeOps, init::Base._InitialValue, A::PermutedDimsArray, dims::Colon)
Base._mapreduce_dim(f, op, init, parent(A), dims)
end
function Base._mapreduce_dim(f::typeof(identity), op::Union{typeof(Base.mul_prod),typeof(*)}, init::Base._InitialValue, A::PermutedDimsArray{<:Union{Real,Complex}}, dims::Colon)
Base._mapreduce_dim(f, op, init, parent(A), dims)
end

function Base.mapreducedim!(f, op, B::AbstractArray{T,N}, A::PermutedDimsArray{T,N,perm,iperm}) where {T,N,perm,iperm}
function Base.mapreducedim!(f, op::CommutativeOps, B::AbstractArray{T,N}, A::PermutedDimsArray{S,N,perm,iperm}) where {T,S,N,perm,iperm}
C = PermutedDimsArray{T,N,iperm,perm,typeof(B)}(B) # make the inverse permutation for the output
Base.mapreducedim!(f, op, C, parent(A))
B
end
function Base.mapreducedim!(f::typeof(identity), op::Union{typeof(Base.mul_prod),typeof(*)}, B::AbstractArray{T,N}, A::PermutedDimsArray{<:Union{Real,Complex},N,perm,iperm}) where {T,N,perm,iperm}
C = PermutedDimsArray{T,N,iperm,perm,typeof(B)}(B) # make the inverse permutation for the output
Base.mapreducedim!(f, op, C, parent(A))
B
Expand Down
2 changes: 1 addition & 1 deletion base/process.jl
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ function open(f::Function, cmds::AbstractCmd, args...; kwargs...)
rethrow()
end
close(P.in)
if !eof(P.out)
if !(eof(P.out)::Bool)
waitkill(P)
throw(_UVError("open(do)", UV_EPIPE))
end
Expand Down
3 changes: 2 additions & 1 deletion base/sort.jl
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,8 @@ const SMALL_ALGORITHM = InsertionSort
const SMALL_THRESHOLD = 20

function sort!(v::AbstractVector, lo::Integer, hi::Integer, ::InsertionSortAlg, o::Ordering)
@inbounds for i = lo+1:hi
lo_plus_1 = (lo + 1)::Integer
@inbounds for i = lo_plus_1:hi
j = i
x = v[i]
while j > lo
Expand Down
2 changes: 1 addition & 1 deletion base/special/exp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ const J_TABLE = (0x0000000000000000, 0xaac00b1afa5abcbe, 0x9b60163da9fb3335, 0xa
# XXX we want to mark :consistent-cy here so that this function can be concrete-folded,
# because the effect analysis currently can't prove it in the presence of `@inbounds` or
# `:boundscheck`, but still the access to `J_TABLE` is really safe here
@noinline Base.@assume_effects :consistent @inline function table_unpack(ind::Int32)
Base.@assume_effects :consistent function table_unpack(ind::Int32)
ind = ind & 255 + 1 # 255 == length(J_TABLE) - 1
j = @inbounds J_TABLE[ind]
jU = reinterpret(Float64, JU_CONST | (j&JU_MASK))
Expand Down
11 changes: 7 additions & 4 deletions base/stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ 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.status == StatusEOF && break
x.throttle = max(nb, x.throttle)
start_reading(x) # ensure we are reading
iolock_end()
Expand Down Expand Up @@ -662,9 +662,11 @@ function uv_readcb(handle::Ptr{Cvoid}, nread::Cssize_t, buf::Ptr{Cvoid})
elseif nread == UV_EOF # libuv called uv_stop_reading already
if stream.status != StatusClosing
stream.status = StatusEOF
if stream isa TTY # TODO: || ccall(:uv_is_writable, Cint, (Ptr{Cvoid},), stream.handle) != 0
# stream can still be used either by reseteof # TODO: or write
notify(stream.cond)
notify(stream.cond)
if stream isa TTY
# stream can still be used by reseteof (or possibly write)
elseif !(stream isa PipeEndpoint) && ccall(:uv_is_writable, Cint, (Ptr{Cvoid},), stream.handle) != 0
# stream can still be used by write
else
# underlying stream is no longer useful: begin finalization
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle)
Expand All @@ -673,6 +675,7 @@ function uv_readcb(handle::Ptr{Cvoid}, nread::Cssize_t, buf::Ptr{Cvoid})
end
else
stream.readerror = _UVError("read", nread)
notify(stream.cond)
# This is a fatal connection error
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle)
stream.status = StatusClosing
Expand Down
Loading