Error messages from Gtk callbacks are not being shown

I’m developing a Gkt.jl application, and errors that happen inside a callback are not being displayed. For example, if you run this code and click the button multiple times:

using Gtk

w = Gtk.Window()
b = Gtk.Button("hello")
push!(w, b)

x = 0

signal_connect(b, "clicked") do widget
    global x += 1
    @info "hi $x"
    @show 32 ÷ (3 - x)
end

Gtk.showall(w)

You’ll see this:

julia> include("/home/user/errtest.jl");

julia> [ Info: hi 1
32 ÷ (3 - x) = 16
[ Info: hi 2
32 ÷ (3 - x) = 32
[ Info: hi 3
[ Info: hi 4
32 ÷ (3 - x) = -32

I understand that Julia sometimes defaults to hiding error messages from secondary threads. Is this something related, or is this specific to Gtk? Is it a bug or a feature? I find it strange because in some situations I do get to see error messages. Would that mean the code was running in the main thread?

I get it that sometimes this behavior is the best, and that forcing every error message to be printed may even be challenging to do. I would absolutely love to see all my error messages, though, since it does not help me when something is not working and I cannot get a clue that it was caused just by a silly typo in a function call, for instance.

What can I do to be able to see all the error messages I may get from every thread in my Gtk.jl application?

I ran into this issue when I first started playing with Julia. What I ended up doing was created a function:

function log_exception(ex, stack)
    local buffer = IOBuffer()
    showerror(buffer, ex)
    write(buffer, "\n\n")
    for bt in stacktrace(stack)
        showerror(buffer, bt)
        write(buffer, '\n')
    end
    seekstart(buffer)
    println(read(buffer, String))
end

Then in ALL my callbacks did:

try
    # Call back code
catch ex
    log_exception(ex, catch_backtrace())
end

I did this back when I first started playing with Julia. So the println(read(buffer, String)) can probably be optimized to println(take!(buffer)) in the log_exception function. And a macro could probably be created to do the try/catch.

1 Like

Thanks so much @pixel27, this is very helpful. Indeed, looks like it could be a useful macro.

I imagine many programmers should feel the same need. I’m not sure how we could take this upstream, though.

I finally got to writing that macro. What’s a good place to submit this? Gtk.jl? Julia itself? Maybe it will just live on forever as a hacky snippet on discourse…

"Catches failures and prints a backtrace, the \"normal\" behavior that is sometimes suppressed in Julia"
macro printbt(f)
    f.args[2] = quote
        try
            $(f.args[2])
        catch ex
            stack = catch_backtrace()
            local buffer = IOBuffer()
            showerror(buffer, ex)
            write(buffer, "\n\n")
            for bt in stacktrace(stack)
                showerror(buffer, bt)
                write(buffer, '\n')
            end
            seekstart(buffer)
            println(read(buffer, String))
        end
    end
    f
end