Skip to content

Commit

Permalink
Isolate each build.jl in a seperate Julia process
Browse files Browse the repository at this point in the history
  • Loading branch information
omus committed Jan 25, 2017
1 parent e904623 commit 5a9836e
Showing 1 changed file with 37 additions and 50 deletions.
87 changes: 37 additions & 50 deletions base/pkg/entry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -580,26 +580,9 @@ function warnbanner(msg...; label="[ WARNING ]", prefix="")
warn(prefix="", "="^cols)
end

function build!(pkgs::Vector, buildstream::IO, seen::Set)
for pkg in pkgs
pkg == "julia" && continue
pkg in seen ? continue : push!(seen,pkg)
Read.isinstalled(pkg) || throw(PkgError("$pkg is not an installed package"))
build!(Read.requires_list(pkg),buildstream,seen)
path = abspath(pkg,"deps","build.jl")
isfile(path) || continue
println(buildstream, path) # send to build process for evalfile
flush(buildstream)
end
end

function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
# To isolate the build from the running Julia process, we
# execute the build.jl files in a separate process that
# is sitting there waiting for paths to evaluate. Errors
# are serialized to errfile for later retrieval into errs[pkg]
errfile = tempname()
close(open(errfile, "w")) # create empty file
function build(pkg::AbstractString, build_file::AbstractString, errfile::AbstractString)
# To isolate the build from the running Julia process, we execute each build.jl file in
# a separate process. Errors are serialized to errfile for later reporting.
# TODO: serialize the same way the load cache does, not with strings
LOAD_PATH = filter(x -> x isa AbstractString, Base.LOAD_PATH)
code = """
Expand All @@ -610,48 +593,52 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
empty!(Base.DL_LOAD_PATH)
append!(Base.DL_LOAD_PATH, $(repr(Base.DL_LOAD_PATH)))
open("$(escape_string(errfile))", "a") do f
pkg = ""
atexit(() -> !isempty(pkg) && run_build())
function run_build()
for path in eachline(STDIN)
pkg = basename(dirname(dirname(path)))
try
info("Building \$pkg")
cd(dirname(path)) do
evalfile(path)
end
catch err
Base.Pkg.Entry.warnbanner(err, label="[ ERROR: \$pkg ]")
serialize(f, pkg)
serialize(f, err)
end
pkg, build_file = "$pkg", "$(escape_string(build_file))"
try
info("Building \$pkg")
cd(dirname(build_file)) do
evalfile(build_file)
end
catch err
Base.Pkg.Entry.warnbanner(err, label="[ ERROR: \$pkg ]")
serialize(f, pkg)
serialize(f, err)
end
run_build()
pkg = ""
end
"""
io, pobj = open(pipeline(detach(`$(Base.julia_cmd()) -O0
--compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no")
--history-file=no
--color=$(Base.have_color ? "yes" : "no")
--eval $code`), stderr=STDERR), "w", STDOUT)
cmd = `$(Base.julia_cmd()) -O0
--compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no")
--history-file=no
--color=$(Base.have_color ? "yes" : "no")
--eval $code`

success(pipeline(cmd, stderr=STDERR))
end

function build!(pkgs::Vector, seen::Set, errfile::AbstractString)
for pkg in pkgs
pkg == "julia" && continue
pkg in seen ? continue : push!(seen,pkg)
Read.isinstalled(pkg) || throw(PkgError("$pkg is not an installed package"))
build!(Read.requires_list(pkg), seen, errfile)
path = abspath(pkg,"deps","build.jl")
isfile(path) || continue
build(pkg, path, errfile) || error("Build process failed.")
end
end

function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
errfile = tempname()
touch(errfile) # create empty file
try
build!(pkgs, io, seen)
close(io)
wait(pobj)
success(pobj) || error("Build process failed.")
build!(pkgs, seen, errfile)
open(errfile, "r") do f
while !eof(f)
pkg = deserialize(f)
err = deserialize(f)
errs[pkg] = err
end
end
catch err
close(io)
isa(err, PkgError) ? wait(pobj) : kill(pobj)
rethrow(err)
finally
isfile(errfile) && Base.rm(errfile)
end
Expand Down

0 comments on commit 5a9836e

Please sign in to comment.