Debugging Julia

#1

After two and half months of intense collaborative development, we (@kristoffer.carlsson, @pfitzseb, and myself, based on original work by @Keno) are pleased to announce a fully-featured debugging stack for Julia. You can read details in a new blog post:

https://julialang.org/blog/2019/03/debuggers

112 Likes

Another Debugger: MagneticReadHead.jl
[ANN] Juno 0.8
#2

How does one run @interpret MyPackageTests for a package that follows the usual separation of src and test directories?

1 Like

#3

Currently it’s a bit more involved than @interpret, unfortunately. Check out the test/utils.jl file and try something like

run_test_by_eval("name of tests", filename, 10^6)

where filename is the absolute path to your test file. 10^6 controls the maximum number of statements the interpreter will run before giving up and switching to compiled code.

0 Likes

#4

Congratulations and great work by all involved!
This has been epic to watch come together,
and the side-effects bring wide ranging improvements to the ecosystem.
(E.g. Revise.jl v2.0)

4 Likes

#5

Awesome stuff. But how do you set a break point?

0 Likes

#6

Am I doing something wrong with JuliaInterpreter, or is broadcasting just not implemented yet?

In [14]: x = rand(1:500, 16000);

In [15]: @interpret x .* x
UndefVarError: .* not defined

Stacktrace:
 [1] top-level scope at /home/adam/.julia/packages/JuliaInterpreter/62ZyY/src/construct.jl:638
 [2] execute_request(::ZMQ.Socket, ::IJulia.Msg) at /home/adam/.julia/packages/IJulia/4UizY/src/execute_request.jl:67
 [3] #invokelatest#1 at ./essentials.jl:742 [inlined]
 [4] invokelatest at ./essentials.jl:741 [inlined]
 [5] eventloop(::ZMQ.Socket) at /home/adam/.julia/packages/IJulia/4UizY/src/eventloop.jl:8
 [6] (::getfield(IJulia, Symbol("##15#18")))() at ./task.jl:259

In any case, all of this is very exciting. Kudos to everyone involved.

0 Likes

#7

Nicely done all.

2 Likes

#8

That’s just a case of Julia itself behaving poorly — and same problem as @which x .* x. Instead try @interpret broadcast(*, x, x) or f(x) = x .* x; @interpret f(x).

3 Likes

#9

Ah. Makes sense. I still haven’t entirely wrapped my head around how arguments to macros work. Thanks!

0 Likes

#10
1 Like

#11

All three packages support the methods in JuliaInterpreter, which is what’s documented in Debugger’s README as linked by Stefan. Moreover,

  • in Juno you can just click in the leftmost column (you have to have fully-updated atom packages ink and julia-client)
  • in Rebugger you can just hit b or c when you come to a line that you want to set a breakpoint at
5 Likes

#12

Very Nice! Thanks a lot for this.

How well does this handle things as @async while true .... end things? Last time I checked it didn’t really. (mainly interested in breakpoint on error stuff)

0 Likes

#13
  1. This is awesome, thanks to all involved!!
  2. You might want to change the README’s Usage section to mention that one has to use Juno.@enter when running in Juno (this confused me until I read the blog post).
0 Likes

#14

It can’t work through tasks, at least not yet. Works fine without the @async, though. In Rebugger:

julia> using Rebugger

julia> function foo()
           while true
               error("oops")
           end
       end
foo (generic function with 1 method)

julia> foo()
ERROR: oops
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] foo() at ./REPL[2]:3
 [3] top-level scope at none:0

interpret> foo()   # here I hit Meta-i followed by Enter (to run until breakpoint)
foo() in Main at REPL[2]:2
foo() in Main at REPL[2]:2
 error(s::AbstractString) in Base at error.jl:33
  s = oops
 33  error(s::AbstractString) = begin
 33          throw(ErrorException(s))
         end

1 Like

#15

Ok cool, Yea the main issues with debugging I’ve had recently were related to some rendering package I’m working on that let’s you asyncronous interact with what’s displayed. But I’ll somehow find a way to use these tools with it during development! Thanks again

0 Likes

#16

How to remove breakpoints when using Debugger.jl? It doesn’t seem to reexport remove() or disable() from JuliaInterpreter.

0 Likes

#17

Hi, confess that have been having some difficulties using the debugger (btw, thanks a LOT for this work). Shouldn’t the MethodError be caught (at least this one isn’t)?

julia> using Debugger, JuliaInterpreter

julia> cd("c:/v");using GMT, Webview

julia> break_on(:error)

julia> grdcontour("@osu91a1f_16.nc", R=:d, J=:H14, cont=10, A="50+f7p", G=(params=(dist="4i",),), L=(-1000,-1), W=((contour=1,pen="thinnest,-"), (annot=1, pen="thin,-")), T=(gap=("0.1i","0.02i"),), Vd=1)
ERROR: MethodError: no method matching *(::String, ::Tuple{String,String})
Closest candidates are:
  *(::Any, ::Any, ::Any, ::Any...) at operators.jl:502
  *(::Union{AbstractChar, AbstractString}, ::Union{AbstractChar, AbstractString}...) at strings/basic.jl:229
  *(::AbstractString, ::Missing) at missing.jl:144
Stacktrace:
 [1] add_opt(::NamedTuple{(:params,),Tuple{NamedTuple{(:dist,),Tuple{String}}}}, ::NamedTuple{(:params,),Tuple{Tuple{String,typeof(GMT.helper_decorated)}}}, ::Nothing) at C:\j\.julia\v0.7\GMT\src\common_options.jl:913
 [2] add_opt(::String, ::Char, ::Dict{Symbol,Any}, ::Array{Symbol,2}, ::NamedTuple{(:params,),Tuple{Tuple{String,typeof(GMT.helper_decorated)}}}, ::Bool, ::Nothing) at C:\j\.julia\v0.7\GMT\src\common_options.jl:869
 [3] add_opt at C:\j\.julia\v0.7\GMT\src\common_options.jl:867 [inlined]
 [4] #grdcontour#80(::Bool, ::Base.Iterators.Pairs{Symbol,Any,NTuple{9,Symbol},NamedTuple{(:R, :J, :cont, :A, :G, :L, :W, :T, :Vd),Tuple{Symbol,Symbol,Int64,String,NamedTuple{(:params,),Tuple{NamedTuple{(:dist,),Tuple{String}}}},Tuple{Int64,Int64},Tuple{NamedTuple{(:contour, :pen),Tuple{Int64,String}},NamedTuple{(:annot, :pen),Tuple{Int64,String}}},NamedTuple{(:gap,),Tuple{Tuple{String,String}}},Int64}}}, ::Function, ::String, ::Array{Any,1}) at C:\j\.julia\v0.7\GMT\src\grdcontour.jl:95
 [5] #grdcontour at .\none:0 [inlined] (repeats 2 times)
 [6] top-level scope at none:0
1 Like

#18

We should reexport them as well. You can use Debugger.JuliaInterpreter.remove for now.

Edit: https://github.com/JuliaDebug/Debugger.jl/pull/133

1 Like

#19

You need to actually run the debugger (with @enter). Otherwise you are just executing normal julia.

1 Like

#20

Ghrrr, sure. I did it yesterday but today I must be convinced that I already know how to use it (which I obviously don’t. Have also issues breaking at deep nested methods but that’s probably for another question).

0 Likes