Skip to content

Properly crash/report error when writing to full filesystem #44535

Open

Description

I've found this interesting article about bugs in "Hello World" style programs, exploring how writing to full files is almost never checked. I was curious to try this in julia, so I wrote the following test.jl:

function main()
    println("Hello World")
    exit(0)
end

main()

and ran it like

$ julia test.jl > /dev/full

which redirects the stdout output to /dev/full, a device that always pretends to be full. I got the following error/stackdump:

$ julia test.jl > /dev/full
error in running finalizer: Base.SystemError(prefix="close", errnum=28, extrainfo=nothing)
#systemerror#69 at ./error.jl:174
systemerror##kw at ./error.jl:174
systemerror##kw at ./error.jl:174
#systemerror#68 at ./error.jl:173 [inlined]
systemerror at ./error.jl:173 [inlined]
close at ./iostream.jl:63
jl_apply at /home/sukera/julia/src/julia.h:1788 [inlined]
run_finalizer at /home/sukera/julia/src/gc.c:278
jl_gc_run_finalizers_in_list at /home/sukera/julia/src/gc.c:365
run_finalizers at /home/sukera/julia/src/gc.c:394 [inlined]
run_finalizers at /home/sukera/julia/src/gc.c:372
jl_atexit_hook at /home/sukera/julia/src/init.c:240
jl_exit at /home/sukera/julia/src/jl_uv.c:633
exit at ./initdefs.jl:28 [inlined]
main at /home/sukera/projects/test.jl:3
unknown function (ip: 0x7fa5d003819f)
jl_apply at /home/sukera/julia/src/julia.h:1788 [inlined]
do_call at /home/sukera/julia/src/interpreter.c:126
eval_value at /home/sukera/julia/src/interpreter.c:215
eval_stmt_value at /home/sukera/julia/src/interpreter.c:166 [inlined]
eval_body at /home/sukera/julia/src/interpreter.c:583
jl_interpret_toplevel_thunk at /home/sukera/julia/src/interpreter.c:731
top-level scope at /home/sukera/projects/test.jl:6
jl_toplevel_eval_flex at /home/sukera/julia/src/toplevel.c:885
jl_toplevel_eval_flex at /home/sukera/julia/src/toplevel.c:830
jl_toplevel_eval_in at /home/sukera/julia/src/toplevel.c:944
eval at ./boot.jl:373 [inlined]
include_string at ./loading.jl:1196
_include at ./loading.jl:1253
include at ./Base.jl:418
exec_options at ./client.jl:292
_start at ./client.jl:495
jfptr__start_40004 at /home/sukera/julia/usr/lib/julia/sys.so (unknown line)
jl_apply at /home/sukera/julia/src/julia.h:1788 [inlined]
true_main at /home/sukera/julia/src/jlapi.c:559
jl_repl_entrypoint at /home/sukera/julia/src/jlapi.c:701
main at julia (unknown line)
__libc_start_call_main at /usr/lib/libc.so.6 (unknown line)
__libc_start_main at /usr/lib/libc.so.6 (unknown line)
_start at julia (unknown line)

and a return code of 0, indicating success:

$ echo $?
0

The program encountered a fatal error and (decisively) shouldn't exit with 0, indicating success - moreover, the error message doesn't really give any indication what went wrong here, so that could be improved as well. Notably, if I remove the exit(0) from the file, the stacktrace shrinks because the default exit path gets hit instead but it still crashes when trying to close the pipe provided as stdout. IMO it should have already crashed at that point, when the device it was trying to write to reported that the write failed:

$ strace -etrace=write julia test.jl > /dev/full
write(5, "*", 1)                        = 1
write(12, "hello world\n", 12)          = -1 ENOSPC (No space left on device)
[...] # the write calls from the error message of `close` follow
+++ exited with 0 +++

As noted in the article, e.g. Python3 dutifully reports the OSError: No space left on device, allowing the bug to be debugged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    error handlingHandling of exceptions by Julia or the userfilesystemUnderlying file system and functions that use itioInvolving the I/O subsystem: libuv, read, write, etc.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions