From 5a9836e1aadee0f45facc0e0504e17f7dd8c1872 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 24 Jan 2017 11:09:40 -0600 Subject: [PATCH] Isolate each build.jl in a seperate Julia process --- base/pkg/entry.jl | 87 ++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 067cad19c5784f..2fd5946543e30e 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -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 = """ @@ -610,37 +593,45 @@ 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) @@ -648,10 +639,6 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) 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