Skip to content

Commit e8ae613

Browse files
authored
[Auditor] Make the auditor multithreaded (#1364)
* [Auditor] Make running the auditor multithreaded * [Auditor] Put lock around use of sandbox mounted on shared directories * [Auditor] More parallelism * Require more thread-safe BinaryBuilderBase * [Auditor] Remove legacy code * [Auditor] Use `patchelf` from `Patchelf_jll` instead the one inside the sandbox * Adapt test to error being thrown inside a task * [AutoBuild] Properly quote `timer` as a string * [Auditor] Put lock around all logging macros * [Auditor] Use `ldid_jll` to avoid calling the executable inside the sandbox * Revert "[Auditor] Use `ldid_jll` to avoid calling the executable inside the sandbox" This reverts commit 583af47. * [Auditor] Remove threading from libtool pass There seems to be some issues with threading, tests don't pass, but this should also not be a time-critical pass, so making it serial shouldn't be _too_ bad. * [Auditor] Use `@spawn` instead of `@threads` for better load balancing * Revert "[Auditor] Use `@spawn` instead of `@threads` for better load balancing" This reverts commit bfbe34e. * [Auditor] Introduce helper function for running external commands * Bump version number
1 parent edecf34 commit e8ae613

13 files changed

+150
-136
lines changed

Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "BinaryBuilder"
22
uuid = "12aac903-9f7c-5d81-afc2-d9565ea332ae"
33
authors = ["Elliot Saba <staticfloat@gmail.com>"]
4-
version = "0.6.3"
4+
version = "0.6.4"
55

66
[deps]
77
ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"
@@ -18,6 +18,7 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
1818
LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36"
1919
ObjectFile = "d8793406-e978-5875-9003-1fc021f44a92"
2020
OutputCollectors = "6c11c7d4-943b-4e2b-80de-f2cfc2930a8c"
21+
Patchelf_jll = "f2cf89d6-2bfd-5c44-bd2c-068eea195c0c"
2122
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
2223
PkgLicenses = "fc669557-7ec9-5e45-bca9-462afbc28879"
2324
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
@@ -33,7 +34,7 @@ ghr_jll = "07c12ed4-43bc-5495-8a2a-d5838ef8d533"
3334

3435
[compat]
3536
ArgParse = "1.1"
36-
BinaryBuilderBase = "1.34"
37+
BinaryBuilderBase = "1.35.2"
3738
Downloads = "1"
3839
GitHub = "5.1"
3940
HTTP = "0.8, 0.9, 1"
@@ -43,6 +44,7 @@ JSON = "0.21"
4344
LoggingExtras = "0.4, 1"
4445
ObjectFile = "0.4.3"
4546
OutputCollectors = "0.1"
47+
Patchelf_jll = "0.14.3"
4648
PkgLicenses = "0.2"
4749
Registrator = "1.1"
4850
RegistryTools = "2.1"

azure-pipelines.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ variables:
3030
BINARYBUILDER_AUTOMATIC_APPLE: true
3131
BINARYBUILDER_USE_CCACHE: true
3232
CI: true
33+
# Auditor is now multi-threaded, run tests with multiple threads
34+
JULIA_NUM_THREADS: 3
3335

3436
jobs:
3537
- job: Info

src/Auditor.jl

Lines changed: 80 additions & 83 deletions
Large diffs are not rendered by default.

src/AutoBuild.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ function autobuild(dir::AbstractString,
10331033
if isempty(readdir(build_path))
10341034
rm(build_path; recursive=true)
10351035
end
1036-
verbose && @info timer
1036+
verbose && @info "$(timer)"
10371037
end
10381038

10391039
# Return our product hashes

src/auditor/codesigning.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ function check_codesigned(path::AbstractString, platform::AbstractPlatform)
55
end
66

77
ur = preferred_runner()(dirname(path); cwd="/workspace/", platform=platform)
8+
# TODO: can we run directly `ldid` with the JLL without entering the sandbox?
89
return run(ur, `/usr/local/bin/ldid -d $(basename(path))`)
910
end
1011

@@ -18,6 +19,7 @@ function ensure_codesigned(path::AbstractString, prefix::Prefix, platform::Abstr
1819
rel_path = relpath(path, prefix.path)
1920
ur = preferred_runner()(prefix.path; cwd="/workspace/", platform=platform)
2021
with_logfile(prefix, "ldid_$(basename(rel_path)).log"; subdir) do io
21-
run(ur, `/usr/local/bin/ldid -S -d $(rel_path)`, io; verbose=verbose)
22+
# TODO: can we run directly `ldid` with the JLL without entering the sandbox?
23+
@lock AUDITOR_SANDBOX_LOCK run(ur, `/usr/local/bin/ldid -S -d $(rel_path)`, io; verbose=verbose)
2224
end
2325
end

src/auditor/compiler_abi.jl

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Base.BinaryPlatforms: detect_libstdcxx_version, detect_cxxstring_abi
22
using ObjectFile
33

4-
csl_warning(lib) = @warn(
4+
csl_warning(lib) = @lock AUDITOR_LOGGING_LOCK @warn(
55
"""
66
To ensure that the correct version of $(lib) is found at runtime, add the following entry to the list of dependencies of this builder
77
@@ -37,12 +37,12 @@ function check_libgfortran_version(oh::ObjectHandle, platform::AbstractPlatform;
3737
if isa(e, InterruptException)
3838
rethrow(e)
3939
end
40-
@warn "$(path(oh)) could not be scanned for libgfortran dependency!" exception=(e, catch_backtrace())
40+
@lock AUDITOR_LOGGING_LOCK @warn "$(path(oh)) could not be scanned for libgfortran dependency!" exception=(e, catch_backtrace())
4141
return true
4242
end
4343

4444
if verbose && version !== nothing
45-
@info("$(path(oh)) locks us to libgfortran v$(version)")
45+
@lock AUDITOR_LOGGING_LOCK @info("$(path(oh)) locks us to libgfortran v$(version)")
4646
end
4747

4848
if !has_csl && version !== nothing
@@ -57,7 +57,7 @@ function check_libgfortran_version(oh::ObjectHandle, platform::AbstractPlatform;
5757
definition in your `build_tarballs.jl` file, add the line:
5858
""", '\n' => ' '))
5959
msg *= "\n\n platforms = expand_gfortran_versions(platforms)"
60-
@warn(msg)
60+
@lock AUDITOR_LOGGING_LOCK @warn(msg)
6161
return false
6262
end
6363

@@ -67,7 +67,7 @@ function check_libgfortran_version(oh::ObjectHandle, platform::AbstractPlatform;
6767
for libgfortran$(libgfortran_version(platform).major). This usually indicates that
6868
the build system is somehow ignoring our choice of compiler!
6969
""", '\n' => ' '))
70-
@warn(msg)
70+
@lock AUDITOR_LOGGING_LOCK @warn(msg)
7171
return false
7272
end
7373
return true
@@ -87,7 +87,7 @@ function check_csl_libs(oh::ObjectHandle, platform::AbstractPlatform; verbose::B
8787
if isa(e, InterruptException)
8888
rethrow(e)
8989
end
90-
@warn "$(path(oh)) could not be scanned for $(lib) dependency!" exception=(e, catch_backtrace())
90+
@lock AUDITOR_LOGGING_LOCK @warn "$(path(oh)) could not be scanned for $(lib) dependency!" exception=(e, catch_backtrace())
9191
return true
9292
end
9393

@@ -140,12 +140,12 @@ function check_libstdcxx_version(oh::ObjectHandle, platform::AbstractPlatform; v
140140
if isa(e, InterruptException)
141141
rethrow(e)
142142
end
143-
@warn "$(path(oh)) could not be scanned for libstdcxx dependency!" exception=(e, catch_backtrace())
143+
@lock AUDITOR_LOGGING_LOCK @warn "$(path(oh)) could not be scanned for libstdcxx dependency!" exception=(e, catch_backtrace())
144144
return true
145145
end
146146

147147
if verbose && libstdcxx_version != nothing
148-
@info("$(path(oh)) locks us to libstdc++ v$(libstdcxx_version)+")
148+
@lock AUDITOR_LOGGING_LOCK @info("$(path(oh)) locks us to libstdc++ v$(libstdcxx_version)+")
149149
end
150150

151151
# This actually isn't critical, so we don't complain. Yet.
@@ -172,6 +172,8 @@ function cppfilt(symbol_names::Vector, platform::AbstractPlatform; strip_undersc
172172

173173
output = IOBuffer()
174174
mktempdir() do dir
175+
# No need to acquire a sandbox lock here because we use a (hopefully)
176+
# different temporary directory for each run.
175177
ur = preferred_runner()(dir; cwd="/workspace/", platform=platform)
176178
cmd = Cmd(`/opt/bin/$(triplet(ur.platform))/c++filt`; ignorestatus=true)
177179
if strip_underscore
@@ -216,7 +218,7 @@ function detect_cxxstring_abi(oh::ObjectHandle, platform::AbstractPlatform)
216218
if isa(e, InterruptException)
217219
rethrow(e)
218220
end
219-
@warn "$(path(oh)) could not be scanned for cxx11 ABI!" exception=(e, catch_backtrace())
221+
@lock AUDITOR_LOGGING_LOCK @warn "$(path(oh)) could not be scanned for cxx11 ABI!" exception=(e, catch_backtrace())
220222
end
221223
return nothing
222224
end
@@ -233,7 +235,7 @@ function check_cxxstring_abi(oh::ObjectHandle, platform::AbstractPlatform; io::I
233235
end
234236

235237
if verbose && cxx_abi != nothing
236-
@info("$(path(oh)) locks us to $(cxx_abi)")
238+
@lock AUDITOR_LOGGING_LOCK @info("$(path(oh)) locks us to $(cxx_abi)")
237239
end
238240

239241
if cxxstring_abi(platform) == nothing && cxx_abi != nothing
@@ -244,7 +246,7 @@ function check_cxxstring_abi(oh::ObjectHandle, platform::AbstractPlatform; io::I
244246
definition in your `build_tarballs.jl` file, add the line:
245247
""", '\n' => ' '))
246248
msg *= "\n\n platforms = expand_cxxstring_abis(platforms)"
247-
@warn(msg)
249+
@lock AUDITOR_LOGGING_LOCK @warn(msg)
248250
return false
249251
end
250252

@@ -255,7 +257,7 @@ function check_cxxstring_abi(oh::ObjectHandle, platform::AbstractPlatform; io::I
255257
indicates that the build system is somehow ignoring our choice of compiler, as we manually
256258
insert the correct compiler flags for this ABI choice!
257259
""", '\n' => ' '))
258-
@warn(msg)
260+
@lock AUDITOR_LOGGING_LOCK @warn(msg)
259261
return false
260262
end
261263
return true

src/auditor/dynamic_linkage.jl

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using ObjectFile.ELF
2+
using Patchelf_jll: patchelf
23

34
"""
45
platform_for_object(oh::ObjectHandle)
@@ -346,17 +347,16 @@ function relink_to_rpath(prefix::Prefix, platform::AbstractPlatform, path::Abstr
346347
libname = basename(old_libpath)
347348
relink_cmd = ``
348349

349-
if Sys.isapple(platform)
350-
install_name_tool = "/opt/bin/$(triplet(ur.platform))/install_name_tool"
351-
relink_cmd = `$install_name_tool -change $(old_libpath) @rpath/$(libname) $(rel_path)`
352-
elseif Sys.islinux(platform) || Sys.isbsd(platform)
353-
patchelf = "/usr/bin/patchelf"
354-
relink_cmd = `$patchelf $(patchelf_flags(platform)) --replace-needed $(old_libpath) $(libname) $(rel_path)`
355-
end
356-
357350
# Create a new linkage that looks like @rpath/$lib on OSX
358351
with_logfile(prefix, "relink_to_rpath_$(basename(rel_path)).log"; subdir) do io
359-
run(ur, relink_cmd, io; verbose=verbose)
352+
if Sys.isapple(platform)
353+
ur = preferred_runner()(prefix.path; cwd="/workspace/", platform=platform)
354+
install_name_tool = "/opt/bin/$(triplet(ur.platform))/install_name_tool"
355+
relink_cmd = `$install_name_tool -change $(old_libpath) @rpath/$(libname) $(rel_path)`
356+
@lock AUDITOR_SANDBOX_LOCK run(ur, relink_cmd, io; verbose=verbose)
357+
elseif Sys.islinux(platform) || Sys.isbsd(platform)
358+
run_with_io(io, `$(patchelf()) $(patchelf_flags(platform)) --replace-needed $(old_libpath) $(libname) $(path)`)
359+
end
360360
end
361361
end
362362

@@ -380,7 +380,7 @@ function fix_identity_mismatch(prefix::Prefix, platform::AbstractPlatform, path:
380380
end
381381

382382
if verbose
383-
@info("Modifying dylib id from \"$(old_id)\" to \"$(new_id)\"")
383+
@lock AUDITOR_LOGGING_LOCK @info("Modifying dylib id from \"$(old_id)\" to \"$(new_id)\"")
384384
end
385385

386386
ur = preferred_runner()(prefix.path; cwd="/workspace/", platform=platform)
@@ -389,7 +389,7 @@ function fix_identity_mismatch(prefix::Prefix, platform::AbstractPlatform, path:
389389

390390
# Create a new linkage that looks like @rpath/$lib on OSX,
391391
with_logfile(prefix, "fix_identity_mismatch_$(basename(rel_path)).log"; subdir) do io
392-
run(ur, id_cmd, io; verbose=verbose)
392+
@lock AUDITOR_SANDBOX_LOCK run(ur, id_cmd, io; verbose=verbose)
393393
end
394394
end
395395

@@ -417,7 +417,6 @@ function update_linkage(prefix::Prefix, platform::AbstractPlatform, path::Abstra
417417
normalize_rpath = rp -> rp
418418
add_rpath = x -> ``
419419
relink = (x, y) -> ``
420-
patchelf = "/usr/bin/patchelf"
421420
install_name_tool = "/opt/bin/$(triplet(ur.platform))/install_name_tool"
422421
if Sys.isapple(platform)
423422
normalize_rpath = rp -> begin
@@ -459,9 +458,9 @@ function update_linkage(prefix::Prefix, platform::AbstractPlatform, path::Abstra
459458
filter!(rp -> !startswith(rp, "/workspace"), rpaths)
460459

461460
rpath_str = join(rpaths, ':')
462-
return `$patchelf $(patchelf_flags(platform)) --set-rpath $(rpath_str) $(rel_path)`
461+
return `$(patchelf()) $(patchelf_flags(platform)) --set-rpath $(rpath_str) $(path)`
463462
end
464-
relink = (op, np) -> `$patchelf $(patchelf_flags(platform)) --replace-needed $(op) $(np) $(rel_path)`
463+
relink = (op, np) -> `$(patchelf()) $(patchelf_flags(platform)) --replace-needed $(op) $(np) $(path)`
465464
end
466465

467466
# If the relative directory doesn't already exist within the RPATH of this
@@ -471,7 +470,11 @@ function update_linkage(prefix::Prefix, platform::AbstractPlatform, path::Abstra
471470
libname = basename(old_libpath)
472471
cmd = add_rpath(normalize_rpath(relpath(new_libdir, dirname(path))))
473472
with_logfile(prefix, "update_rpath_$(basename(path))_$(libname).log"; subdir) do io
474-
run(ur, cmd, io; verbose=verbose)
473+
if Sys.isapple(platform)
474+
@lock AUDITOR_SANDBOX_LOCK run(ur, cmd, io; verbose=verbose)
475+
elseif Sys.islinux(platform) || Sys.isbsd(platform)
476+
run_with_io(io, cmd)
477+
end
475478
end
476479
end
477480

@@ -490,7 +493,11 @@ function update_linkage(prefix::Prefix, platform::AbstractPlatform, path::Abstra
490493
end
491494
cmd = relink(old_libpath, new_libpath)
492495
with_logfile(prefix, "update_linkage_$(basename(path))_$(basename(old_libpath)).log"; subdir) do io
493-
run(ur, cmd, io; verbose=verbose)
496+
if Sys.isapple(platform)
497+
@lock AUDITOR_SANDBOX_LOCK run(ur, cmd, io; verbose=verbose)
498+
elseif Sys.islinux(platform) || Sys.isbsd(platform)
499+
run_with_io(io, cmd)
500+
end
494501
end
495502

496503
return new_libpath

src/auditor/extra_checks.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function check_os_abi(oh::ObjectHandle, p::AbstractPlatform, rest...; verbose::B
1313
$(basename(path(oh))) has an ELF header OS/ABI value that is not set to FreeBSD
1414
($(ELF.ELFOSABI_FREEBSD)), this may be an issue at link time
1515
""", '\n' => ' ')
16-
@warn(strip(msg))
16+
@lock AUDITOR_LOGGING_LOCK @warn(strip(msg))
1717
end
1818
return false
1919
end
@@ -24,7 +24,7 @@ function check_os_abi(oh::ObjectHandle, p::AbstractPlatform, rest...; verbose::B
2424
# means "no specific float ABI", `0x400` == EF_ARM_ABI_FLOAT_HARD.
2525
if header(oh).e_flags & 0xF00 (0x000, 0x400)
2626
if verbose
27-
@error("$(basename(path(oh))) does not match the hard-float ABI")
27+
@lock AUDITOR_LOGGING_LOCK @error("$(basename(path(oh))) does not match the hard-float ABI")
2828
end
2929
return false
3030
end

src/auditor/filesystems.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function check_case_sensitivity(prefix::Prefix)
66
for f in list
77
lf = lowercase(f)
88
if lf in lowered
9-
@warn("$(relpath(joinpath(root, f), prefix.path)) causes a case-sensitivity ambiguity!")
9+
@lock AUDITOR_LOGGING_LOCK @warn("$(relpath(joinpath(root, f), prefix.path)) causes a case-sensitivity ambiguity!")
1010
all_ok = false
1111
end
1212
push!(lowered, lf)
@@ -31,12 +31,12 @@ function check_absolute_paths(prefix::Prefix, all_files::Vector; silent::Bool =
3131
file_contents = String(read(f))
3232
if occursin(prefix.path, file_contents)
3333
if !silent
34-
@warn("$(relpath(f, prefix.path)) contains an absolute path")
34+
@lock AUDITOR_LOGGING_LOCK @warn("$(relpath(f, prefix.path)) contains an absolute path")
3535
end
3636
end
3737
catch
3838
if !silent
39-
@warn("Skipping abspath scanning of $(f), as we can't open it")
39+
@lock AUDITOR_LOGGING_LOCK @warn("Skipping abspath scanning of $(f), as we can't open it")
4040
end
4141
end
4242
end
@@ -51,7 +51,7 @@ function ensure_executability(oh::ObjectHandle; verbose::Bool=false, silent::Boo
5151
# Check whether the file has executable permission for all
5252
if old_mode & read_mask != read_mask
5353
if verbose
54-
@info "Making $(path(oh)) executable"
54+
@lock AUDITOR_LOGGING_LOCK @info "Making $(path(oh)) executable"
5555
end
5656
try
5757
# Add executable permission for all users that can read the file
@@ -61,7 +61,7 @@ function ensure_executability(oh::ObjectHandle; verbose::Bool=false, silent::Boo
6161
rethrow(e)
6262
end
6363
if !silent
64-
@warn "$(path(oh)) could not be made executable!" exception=(e, catch_backtrace())
64+
@lock AUDITOR_LOGGING_LOCK @warn "$(path(oh)) could not be made executable!" exception=(e, catch_backtrace())
6565
end
6666
end
6767
end

src/auditor/instruction_set.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function instruction_mnemonics(path::AbstractString, platform::AbstractPlatform)
4141
else
4242
objdump_cmd = "\${target}-objdump -d $(basename(path))"
4343
end
44-
run_interactive(ur, Cmd(`/bin/bash -c "$(objdump_cmd)"`; ignorestatus=true); stdout=output, stderr=devnull)
44+
@lock AUDITOR_SANDBOX_LOCK run_interactive(ur, Cmd(`/bin/bash -c "$(objdump_cmd)"`; ignorestatus=true); stdout=output, stderr=devnull)
4545
seekstart(output)
4646

4747
for line in eachline(output)
@@ -162,7 +162,7 @@ function analyze_instruction_set(oh::ObjectHandle, platform::AbstractPlatform; v
162162
the proper instruction set internally. Would have chosen
163163
$(min_march), instead choosing $(generic_march(platform)).
164164
""", '\n' => ' ')
165-
@warn(strip(msg))
165+
@lock AUDITOR_LOGGING_LOCK @warn(strip(msg))
166166
end
167167
return generic_march(platform)
168168
end

0 commit comments

Comments
 (0)