Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap remote exceptions in Malt.RemoteException #57

Merged
merged 4 commits into from
Sep 12, 2023
Merged

Conversation

fonsp
Copy link
Member

@fonsp fonsp commented Sep 12, 2023

Fix #31

New type:

struct RemoteException <: Exception
    worker::AbstractWorker
    message::String
end

Example:

julia> Malt.remote_eval_fetch(m1, :(sqrt(-1)))
ERROR: Remote exception from Malt.Worker on port 9115:

DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
 [1] throw_complex_domainerror(f::Symbol, x::Float64)
   @ Base.Math ./math.jl:33
 [2] sqrt
   @ ./math.jl:591 [inlined]
 [3] sqrt(x::Int64)
   @ Base.Math ./math.jl:1372
 [4] top-level scope
   @ none:1
 [5] eval
   @ ./boot.jl:368 [inlined]
 [6] macro expansion
   @ ~/Documents/Malt.jl/src/worker.jl:118 [inlined]
 [7] (::var"#1#3"{Sockets.TCPSocket, UInt64, Bool, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, Tuple{Module, Expr}, typeof(Core.eval)})()
   @ Main ./task.jl:484
Stacktrace:
 [1] unwrap_worker_result(worker::Malt.Worker, result::Malt.WorkerResult)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:69
 [2] _wait_for_response(worker::Malt.Worker, msg_id::UInt64)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:304
 [3] _send_receive
   @ ~/Documents/Malt.jl/src/Malt.jl:315 [inlined]
 [4] #remotecall_fetch#41
   @ ~/Documents/Malt.jl/src/Malt.jl:385 [inlined]
 [5] remotecall_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:384 [inlined]
 [6] remote_eval_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:463 [inlined]
 [7] remote_eval_fetch(w::Malt.Worker, expr::Expr)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:464
 [8] top-level scope
   @ REPL[5]:1

This also helps to normalize the exception behaviour of the three backends.

No original exception, only String

I decided to use a different API from Distributed. Distributed tries to serialize the original exception object and stacktrace, and it has a special error-failed-to-deserialize-flow for when this goes wrong (but then you don't see any info).

I think that this will occur too often with Malt use-cases (because Malt is for non-homogenous computing, so types are non shared), and I think a Maltonian program would write a specific try-catch handler on the worker end, and uncaught remote exceptions are only meant to be consumed by humans (so a string is fine).

So in Malt, we call showerror on the worker end to get the error message + stacktrace as a String, and this is what is returned to the host. This means that the error will always be visible to the host.

New behaviour

Of all three worker types:

julia> import Malt

julia> m1 = Malt.Worker();

julia> m2 = Malt.InProcessWorker();

julia> m3 = Malt.DistributedStdlibWorker();

julia> Malt.remote_eval_fetch(m1, :(sqrt(-1)))
ERROR: Remote exception from Malt.Worker on port 9115:

DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
 [1] throw_complex_domainerror(f::Symbol, x::Float64)
   @ Base.Math ./math.jl:33
 [2] sqrt
   @ ./math.jl:591 [inlined]
 [3] sqrt(x::Int64)
   @ Base.Math ./math.jl:1372
 [4] top-level scope
   @ none:1
 [5] eval
   @ ./boot.jl:368 [inlined]
 [6] macro expansion
   @ ~/Documents/Malt.jl/src/worker.jl:118 [inlined]
 [7] (::var"#1#3"{Sockets.TCPSocket, UInt64, Bool, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, Tuple{Module, Expr}, typeof(Core.eval)})()
   @ Main ./task.jl:484
Stacktrace:
 [1] unwrap_worker_result(worker::Malt.Worker, result::Malt.WorkerResult)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:69
 [2] _wait_for_response(worker::Malt.Worker, msg_id::UInt64)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:304
 [3] _send_receive
   @ ~/Documents/Malt.jl/src/Malt.jl:315 [inlined]
 [4] #remotecall_fetch#41
   @ ~/Documents/Malt.jl/src/Malt.jl:385 [inlined]
 [5] remotecall_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:384 [inlined]
 [6] remote_eval_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:463 [inlined]
 [7] remote_eval_fetch(w::Malt.Worker, expr::Expr)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:464
 [8] top-level scope
   @ REPL[5]:1

julia> Malt.remote_eval_fetch(m2, :(sqrt(-1)))
ERROR: Remote exception from Malt.InProcessWorker in module Main:

DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
  [1] throw_complex_domainerror(f::Symbol, x::Float64)
    @ Base.Math ./math.jl:33
  [2] sqrt
    @ ./math.jl:591 [inlined]
  [3] sqrt(x::Int64)
    @ Base.Math ./math.jl:1372
  [4] top-level scope
    @ none:1
  [5] eval(m::Module, e::Any)
    @ Core ./boot.jl:368
  [6] remotecall_fetch(::typeof(Core.eval), ::Malt.InProcessWorker, ::Module, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Malt ~/Documents/Malt.jl/src/Malt.jl:361
  [7] remotecall_fetch
    @ ~/Documents/Malt.jl/src/Malt.jl:359 [inlined]
  [8] remote_eval_fetch
    @ ~/Documents/Malt.jl/src/Malt.jl:463 [inlined]
  [9] remote_eval_fetch(w::Malt.InProcessWorker, expr::Expr)
    @ Malt ~/Documents/Malt.jl/src/Malt.jl:464
 [10] top-level scope
    @ REPL[6]:1
 [11] eval
    @ ./boot.jl:368 [inlined]
 [12] eval_user_input(ast::Any, backend::REPL.REPLBackend)
    @ REPL /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:151
 [13] repl_backend_loop(backend::REPL.REPLBackend)
    @ REPL /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:247
 [14] start_repl_backend(backend::REPL.REPLBackend, consumer::Any)
    @ REPL /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:232
 [15] run_repl(repl::REPL.AbstractREPL, consumer::Any; backend_on_current_task::Bool)
    @ REPL /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:369
 [16] run_repl(repl::REPL.AbstractREPL, consumer::Any)
    @ REPL /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/REPL/src/REPL.jl:355
 [17] (::Base.var"#967#969"{Bool, Bool, Bool})(REPL::Module)
    @ Base ./client.jl:419
 [18] #invokelatest#2
    @ ./essentials.jl:729 [inlined]
 [19] invokelatest
    @ ./essentials.jl:726 [inlined]
 [20] run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)
    @ Base ./client.jl:404
 [21] exec_options(opts::Base.JLOptions)
    @ Base ./client.jl:318
 [22] _start()
    @ Base ./client.jl:522
Stacktrace:
 [1] remotecall_fetch(::typeof(Core.eval), ::Malt.InProcessWorker, ::Module, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:363
 [2] remotecall_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:359 [inlined]
 [3] remote_eval_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:463 [inlined]
 [4] remote_eval_fetch(w::Malt.InProcessWorker, expr::Expr)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:464
 [5] top-level scope
   @ REPL[6]:1

caused by: DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
  [1] throw_complex_domainerror(f::Symbol, x::Float64)
    @ Base.Math ./math.jl:33
  [2] sqrt
    @ ./math.jl:591 [inlined]
  [3] sqrt(x::Int64)
    @ Base.Math ./math.jl:1372
  [4] top-level scope
    @ none:1
  [5] eval(m::Module, e::Any)
    @ Core ./boot.jl:368
  [6] remotecall_fetch(::typeof(Core.eval), ::Malt.InProcessWorker, ::Module, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Malt ~/Documents/Malt.jl/src/Malt.jl:361
  [7] remotecall_fetch
    @ ~/Documents/Malt.jl/src/Malt.jl:359 [inlined]
  [8] remote_eval_fetch
    @ ~/Documents/Malt.jl/src/Malt.jl:463 [inlined]
  [9] remote_eval_fetch(w::Malt.InProcessWorker, expr::Expr)
    @ Malt ~/Documents/Malt.jl/src/Malt.jl:464
 [10] top-level scope
    @ REPL[6]:1

julia> Malt.remote_eval_fetch(m3, :(sqrt(-1)))
ERROR: Remote exception from Malt.DistributedStdlibWorker with pid 2:

DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
  [1] throw_complex_domainerror
    @ ./math.jl:33
  [2] sqrt
    @ ./math.jl:591 [inlined]
  [3] sqrt
    @ ./math.jl:1372
  [4] top-level scope
    @ none:1
  [5] eval
    @ ./boot.jl:368
  [6] #invokelatest#2
    @ ./essentials.jl:729
  [7] invokelatest
    @ ./essentials.jl:726
  [8] #110
    @ /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/process_messages.jl:285
  [9] run_work_thunk
    @ /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/process_messages.jl:70
 [10] macro expansion
    @ /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/process_messages.jl:285 [inlined]
 [11] #109
    @ ./task.jl:484
Stacktrace:
 [1] remotecall_fetch(::Function, ::Malt.DistributedStdlibWorker, ::Module, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Malt ~/Documents/Malt.jl/src/DistributedStdlibWorker.jl:47
 [2] remotecall_fetch
   @ ~/Documents/Malt.jl/src/DistributedStdlibWorker.jl:58 [inlined]
 [3] remote_eval_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:463 [inlined]
 [4] remote_eval_fetch(w::Malt.DistributedStdlibWorker, expr::Expr)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:464
 [5] top-level scope
   @ REPL[7]:1

caused by: On worker 2:
DomainError with -1.0:
sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).
Stacktrace:
  [1] throw_complex_domainerror
    @ ./math.jl:33
  [2] sqrt
    @ ./math.jl:591 [inlined]
  [3] sqrt
    @ ./math.jl:1372
  [4] top-level scope
    @ none:1
  [5] eval
    @ ./boot.jl:368
  [6] #invokelatest#2
    @ ./essentials.jl:729
  [7] invokelatest
    @ ./essentials.jl:726
  [8] #110
    @ /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/process_messages.jl:285
  [9] run_work_thunk
    @ /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/process_messages.jl:70
 [10] macro expansion
    @ /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/process_messages.jl:285 [inlined]
 [11] #109
    @ ./task.jl:484
Stacktrace:
 [1] remotecall_fetch(::Function, ::Distributed.Worker, ::Module, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Distributed /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/remotecall.jl:465
 [2] remotecall_fetch(::Function, ::Distributed.Worker, ::Module, ::Vararg{Any})
   @ Distributed /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/remotecall.jl:454
 [3] remotecall_fetch(::Function, ::Int64, ::Module, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Distributed /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/remotecall.jl:492
 [4] remotecall_fetch(::Function, ::Int64, ::Module, ::Vararg{Any})
   @ Distributed /Applications/Julia-1.8 ARM.app/Contents/Resources/julia/share/julia/stdlib/v1.8/Distributed/src/remotecall.jl:492
 [5] remotecall_fetch(::Function, ::Malt.DistributedStdlibWorker, ::Module, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Malt ~/Documents/Malt.jl/src/DistributedStdlibWorker.jl:44
 [6] remotecall_fetch
   @ ~/Documents/Malt.jl/src/DistributedStdlibWorker.jl:58 [inlined]
 [7] remote_eval_fetch
   @ ~/Documents/Malt.jl/src/Malt.jl:463 [inlined]
 [8] remote_eval_fetch(w::Malt.DistributedStdlibWorker, expr::Expr)
   @ Malt ~/Documents/Malt.jl/src/Malt.jl:464
 [9] top-level scope
   @ REPL[7]:1

@fonsp fonsp merged commit 92b515b into main Sep 12, 2023
16 checks passed
@fonsp fonsp deleted the RemoteException branch September 12, 2023 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

remote_eval_fetch(sqrt(-1)) should throw, not return an Exception
1 participant