diff --git a/src/cluster.jl b/src/cluster.jl index 898a08b..0e85bbb 100644 --- a/src/cluster.jl +++ b/src/cluster.jl @@ -240,7 +240,8 @@ worker_timeout() = parse(Float64, get(ENV, "JULIA_WORKER_TIMEOUT", "60.0")) ## worker creation and setup ## """ - start_worker([out::IO=stdout], cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true) + start_worker([out::IO=stdout], cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true, + exit_on_close::Bool=true, bind_addr=nothing) `start_worker` is an internal function which is the default entry point for worker processes connecting via TCP/IP. It sets up the process as a Julia cluster @@ -253,7 +254,8 @@ The function reads the cookie from stdin if required, and listens on a free por tasks to process incoming TCP connections and requests. It also (optionally) closes stdin and redirects stderr to stdout. -If a specific interface is not specified through `--bind-to` it will make a +The interface to listen on is taken from `bind_addr` if it is set, otherwise +from the `--bind-to` command line option. If neither is given it will make a best-effort attempt to pick the fastest available network interface to listen on. The heuristics it uses for this depend on the system configuration and should not be relied upon to always pick the fastest interface. @@ -261,7 +263,8 @@ should not be relied upon to always pick the fastest interface. It does not return. """ start_worker(cookie::AbstractString=readline(stdin); kwargs...) = start_worker(stdout, cookie; kwargs...) -function start_worker(out::IO, cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true, exit_on_close::Bool=true) +function start_worker(out::IO, cookie::AbstractString=readline(stdin); close_stdin::Bool=true, stderr_to_stdout::Bool=true, + exit_on_close::Bool=true, bind_addr=nothing) init_multi() if close_stdin # workers will not use it @@ -271,6 +274,9 @@ function start_worker(out::IO, cookie::AbstractString=readline(stdin); close_std stderr_to_stdout && redirect_stderr(stdout) init_worker(cookie) + if !isnothing(bind_addr) + CTX[].lproc.bind_addr = bind_addr + end interface = parse(IPAddr, CTX[].lproc.bind_addr) if CTX[].lproc.bind_port == 0 (port, sock) = listenany(interface, CTX[].lproc.bind_port_hint) diff --git a/src/managers.jl b/src/managers.jl index 7f270a3..4266e50 100644 --- a/src/managers.jl +++ b/src/managers.jl @@ -497,7 +497,7 @@ function launch(manager::LocalManager, params::Dict, launched::Array, c::Conditi dir = params[:dir] exename = params[:exename] exeflags = params[:exeflags] - bind_to = manager.restrict ? `127.0.0.1` : `$(CTX[].lproc.bind_addr)` + bind_addr = manager.restrict ? "127.0.0.1" : CTX[].lproc.bind_addr env = Dict{String,String}(params[:env]) # TODO: Maybe this belongs in base/initdefs.jl as a package_environment() function @@ -539,14 +539,15 @@ function launch(manager::LocalManager, params::Dict, launched::Array, c::Conditi Base.link_pipe!(pipe; reader_supports_async=true, writer_supports_async=true) task = Threads.@spawn @with CTX => worker_ctx begin - start_worker(pipe.in, cookie; close_stdin=false, stderr_to_stdout=false, exit_on_close=false) + start_worker(pipe.in, cookie; close_stdin=false, stderr_to_stdout=false, + exit_on_close=false, bind_addr) end errormonitor(task) wconfig.io = pipe.out wconfig.userdata = (; ctx=worker_ctx, task, pipe) else - cmd = `$(julia_cmd(exename)) $exeflags --bind-to $bind_to $(get_worker_arg())` + cmd = `$(julia_cmd(exename)) $exeflags --bind-to $bind_addr $(get_worker_arg())` proc = open(detach(setenv(addenv(cmd, env), dir=dir)), "r+") write_cookie(proc) diff --git a/src/precompile.jl b/src/precompile.jl index bd6dd13..907adb9 100644 --- a/src/precompile.jl +++ b/src/precompile.jl @@ -1,10 +1,14 @@ using PrecompileTools: @compile_workload @compile_workload begin - # Run the workload in a separate ClusterContext so the default one stays clean - ClusterContext() do - # Use an in-process worker to avoid spawning a real process during precompilation - pid = only(addprocs(LocalManager(1, true, true))) - rmprocs(pid) + try + # Run the workload in a separate ClusterContext so the default one stays clean + ClusterContext() do + # Use an in-process worker to avoid spawning a real process during precompilation + pid = only(addprocs(LocalManager(1, true, true))) + rmprocs(pid) + end + catch ex + @error "DistributedNext precompilation failed, please report this" exception=(ex, catch_backtrace()) end end