I have a fairly simple piece of code that does:
function recv_message(client::LEDCubeClient)
buf = UInt8[]
byte = read(client.sock, UInt8)
while byte != 0x00
push!(buf, byte)
byte = read(client.sock, UInt8)
end
recv_msg = COBSReduced.cobs_decode(buf)
decoder = ProtoDecoder(IOBuffer(recv_msg))
return decode(decoder, MatrixServerMessage)
end
where client.sock is a TCPSocket.
It fails with:
Precompiling packages finished.
2 dependencies successfully precompiled in 2 seconds. 13 already precompiled.
◑ Compiling...Verifier error #1: unresolved call from statement (Base.var"#readcb_specialized#uv_readcb##0"())(ccall(:jl_value_ptr)::Base.LibuvStream, nread::Any, ccall(:jl_uv_buf_len)::UInt64)::Any
Stacktrace:
[1] uv_readcb(handle::Ptr{Nothing}, nread::Int64, buf::Ptr{Nothing})
@ Base stream.jl:720
Trim verify finished with 1 error, 0 warnings.
I have a horrible fix of monkey-patching Base:
function Base.uv_readcb(handle::Ptr{Cvoid}, nread::Cssize_t, buf::Ptr{Cvoid})
stream_unknown_type = Base.@handle_as handle Base.LibuvStream
nrequested = ccall(:jl_uv_buf_len, Csize_t, (Ptr{Cvoid},), buf)
function readcb_specialized(stream::Base.LibuvStream, nread::Int, nrequested::UInt)
lock(stream.cond)
if nread < 0
if nread == Base.UV_ENOBUFS && nrequested == 0
# remind the client that stream.buffer is full
notify(stream.cond)
elseif nread == Base.UV_EOF # libuv called uv_stop_reading already
if stream.status != Base.StatusClosing
stream.status = Base.StatusEOF
notify(stream.cond)
if stream isa Base.TTY
# stream can still be used by reseteof (or possibly write)
elseif !(stream isa Base.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)
stream.status = Base.StatusClosing
end
end
else
stream.readerror = Base._UVError("read", nread)
notify(stream.cond)
# This is a fatal connection error
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), stream.handle)
stream.status = Base.StatusClosing
end
else
Base.notify_filled(stream.buffer, nread)
notify(stream.cond)
end
unlock(stream.cond)
# Stop background reading when
# 1) there's nobody paying attention to the data we are reading
# 2) we have accumulated a lot of unread data OR
# 3) we have an alternate buffer that has reached its limit.
if stream.status == Base.StatusPaused ||
(stream.status == Base.StatusActive &&
((bytesavailable(stream.buffer) >= stream.throttle) ||
(bytesavailable(stream.buffer) >= stream.buffer.maxsize)))
# save cycles by stopping kernel notifications from arriving
ccall(:uv_read_stop, Cint, (Ptr{Cvoid},), stream)
stream.status = Base.StatusOpen
end
nothing
end
if stream_unknown_type isa TCPSocket
return readcb_specialized(stream_unknown_type::TCPSocket, nread, nrequested)
else
return readcb_specialized(stream_unknown_type, nread, nrequested)
end
nothing
end
Version
julia> versioninfo()
Julia Version 1.12.5
Commit 5fe89b8ddc1 (2026-02-09 16:05 UTC)
Build Info:
Official https://julialang.org release
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 16 × AMD Ryzen 7 7840U w/ Radeon 780M Graphics
WORD_SIZE: 64
LLVM: libLLVM-18.1.7 (ORCJIT, znver4)
GC: Built with stock GC
(@v1.12) pkg> app st
[acedd4c2] JuliaC v0.3.1
juliac ~/.julia/juliaup/julia-1.12.5+0.x64.linux.gnu/bin/julia
I have a fairly simple piece of code that does:
where
client.sockis aTCPSocket.It fails with:
I have a horrible fix of monkey-patching Base:
Version