printf() and stdio in the Julia runtime-and-stdio-in-the-Julia-runtime)
… and corresponding output functions:
int jl_printf(uv_stream_t *s, const char *format, ...);
int jl_vprintf(uv_stream_t *s, const char *format, va_list args);
These printf
functions are used by the .c
files in the src/
and cli/
directories wherever stdio is needed to ensure that output buffering is handled in a unified way.
In special cases, like signal handlers, where the full libuv infrastructure is too heavy, jl_safe_printf()
can be used to directly to STDERR_FILENO
:
Base.stdin, and Base.stderr are bound to the JL_STD*
libuv streams defined in the runtime.
reinit_stdio()
uses to retrieve pointers to JL_STD*
and calls jl_uv_handle_type()
to inspect the type of each stream. It then creates a Julia Base.IOStream
, Base.TTY
or Base.PipeEndpoint
object to represent each stream, e.g.:
Tuple{Base.TTY,Base.TTY,Base.TTY}
$ julia -e 'println(typeof((stdin, stdout, stderr)))' < /dev/null 2>/dev/null
Tuple{IOStream,Base.TTY,IOStream}
$ echo hello | julia -e 'println(typeof((stdin, stdout, stderr)))' | cat
The Base.read and methods for these streams use ccall to call libuv wrappers in src/jl_uv.c
, e.g.:
The libuv streams relied upon by jl_printf()
etc., are not available until midway through initialization of the runtime (see init.c
, init_stdio()
). Error messages or warnings that need to be printed before this are routed to the standard C library fwrite()
function by the following mechanism:
In sys.c
, the JL_STD*
stream pointers are statically initialized to integer constants: STD*_FILENO (0, 1 and 2)
. In jl_uv.c
the jl_uv_puts()
function checks its uv_stream_t* stream
argument and calls fwrite()
if stream is set to STDOUT_FILENO
or STDERR_FILENO
.
The src/support/ios.c
library is inherited from . It provides cross-platform buffered file IO and in-memory temporary buffers.
ios.c
is still used by:
src/dump.c
– for serialization file IO and for memory buffers.src/staticdata.c
– for serialization file IO and for memory buffers.base/iostream.jl
– for file IO (seebase/fs.jl
for libuv equivalent).
Use of ios.c
in these modules is mostly self-contained and separated from the libuv I/O system. However, there is one place where femtolisp calls through to jl_printf()
with a legacy ios_t
stream.
There is a hack in ios.h
that makes the ios_t.bm
field line up with the uv_stream_t.type
and ensures that the values used for ios_t.bm
to not overlap with valid UV_HANDLE_TYPE
values. This allows uv_stream_t
pointers to point to ios_t
streams.
if (stream->type > UV_HANDLE_TYPE_MAX) {
return ios_write((ios_t*)stream, str, n);