I'd like to redefine or overwrite some functions in Base
, without the users noticing about this. I found this trick sometime ago:
original_stderr = STDERR
redirect_stderr()
# code
redirect_stderr(original_stderr)
This became a repetitive pattern for me, so I did a macro:
macro suppress_err(block)
quote
orig_err = STDERR
redirect_stderr()
val = $block
redirect_stderr(orig_err)
val
end
end
But it has never behaved as expected (even without the macro):
- jl_uv_writecb() ERROR: broken pipe EPIPE on windows()
- REPL: jl_uv_writecb() broken pipe EPIPE
In Windows:
julia> @suppress_err warn()
julia> @suppress_err error()
ERROR:
in error at error.jl:22
Windows Subsystem for Linux:
julia> @suppress_err warn()
[1] 17 abort (core dumped) julia
julia 7.69s user 2.36s system 106% cpu 9.441 total
In Linux:
julia> @suppress_err +(x, y) = x - y
ERROR: UndefVarError: #11#x not defined
in eval(::Module, ::Any) at ./boot.jl:234
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
Obviously I'm doing something terribly wrong, what's the correct way I should tackle this? Should I raise an issue at the Julia repository?
I have also tried using close
on both err_rd, err_wr = redirect_stderr()
, before redirecting again to the original STDERR
without success.
Update:
I have made a Suppressor package with what I've done so you can easily test it:
Pkg.clone("https://github.com/Ismael-VC/Suppressor.jl")
All the macros have the same basic form:
macro suppress_err(block)
quote
let
if ccall(:jl_generating_output, Cint, ()) == 0
ORIGINAL_STDERR = STDERR
err_rd, err_wr = redirect_stderr()
value = $(esc(block))
REDIRECTED_STDERR = STDERR
redirect_stderr(ORIGINAL_STDERR)
# This doesn't help:
# close(err_rd)
# close(err_wr)
return value
end
end
end
end
- I added the safety check from
JuliaParser
here
You need to keep a reference to the return value of the original
redirect_stderr
. It returns both the read and the write end, but while the write end is stored inSTDERR
, the read end is not, so the GC may decide to get rid of it. If that happens, it gets closed at the system level, so when julia tries to write to it, it gets that error.Note: example code below updated as per current
Suppressor.jl
version.