Skip to content

Commit

Permalink
make load_library() panic on some errors when err=0 (JuliaLang#47343
Browse files Browse the repository at this point in the history
)

load_library with `err=0` now panics on errors, provided that the
file exists. It used to never panic on errors, leading to
confusion between when cases the libjuliacodegen library had been
intentionally removed and when it tried but failed to load it.

Fixes JuliaLang#47027
  • Loading branch information
apaz-cli authored Oct 28, 2022
1 parent bbdee0b commit 9f843b8
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
18 changes: 16 additions & 2 deletions cli/loader_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ extern "C" {
/* Bring in helper functions for windows without libgcc. */
#ifdef _OS_WINDOWS_
#include "loader_win_utils.c"

#include <fileapi.h>
static int win_file_exists(wchar_t* wpath) {
return GetFileAttributesW(wpath) == INVALID_FILE_ATTRIBUTES ? 0 : 1;
}
#endif

// Save DEP_LIBS to a variable that is explicitly sized for expansion
Expand All @@ -31,6 +36,13 @@ void jl_loader_print_stderr3(const char * msg1, const char * msg2, const char *
}

/* Wrapper around dlopen(), with extra relative pathing thrown in*/
/* If err, then loads the library successfully or panics.
* If !err, then loads the library or returns null if the file does not exist,
* or panics if opening failed for any other reason. */
/* Currently the only use of this function with !err is in opening libjulia-codegen,
* which the user can delete to save space if generating new code is not necessary.
* However, if it exists and cannot be loaded, that's a problem. So, we alert the user
* and abort the process. */
static void * load_library(const char * rel_path, const char * src_dir, int err) {
void * handle = NULL;

Expand All @@ -55,19 +67,21 @@ static void * load_library(const char * rel_path, const char * src_dir, int err)
strncat(path, rel_path, sizeof(path) - 1);

#if defined(_OS_WINDOWS_)
#define PATH_EXISTS() win_file_exists(wpath)
wchar_t wpath[2*JL_PATH_MAX + 1] = {0};
if (!utf8_to_wchar(path, wpath, 2*JL_PATH_MAX)) {
jl_loader_print_stderr3("ERROR: Unable to convert path ", path, " to wide string!\n");
exit(1);
}
handle = (void *)LoadLibraryExW(wpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
#else
#define PATH_EXISTS() !access(path, F_OK)
handle = dlopen(path, RTLD_NOW | (err ? RTLD_GLOBAL : RTLD_LOCAL));
#endif

if (handle == NULL) {
if (!err)
if (!err && !PATH_EXISTS())
return NULL;
#undef PATH_EXISTS
jl_loader_print_stderr3("ERROR: Unable to load dependent library ", path, "\n");
#if defined(_OS_WINDOWS_)
LPWSTR wmsg = TEXT("");
Expand Down
15 changes: 14 additions & 1 deletion test/compiler/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -689,12 +689,25 @@ mktempdir() do pfx
cp(dirname(Sys.BINDIR), pfx; force=true)
libpath = relpath(dirname(dlpath(libjulia_codegen_name())), dirname(Sys.BINDIR))
libs_deleted = 0
for f in filter(f -> startswith(f, "libjulia-codegen"), readdir(joinpath(pfx, libpath)))
libfiles = filter(f -> startswith(f, "libjulia-codegen"), readdir(joinpath(pfx, libpath)))
for f in libfiles
rm(joinpath(pfx, libpath, f); force=true, recursive=true)
libs_deleted += 1
end
@test libs_deleted > 0
@test readchomp(`$pfx/bin/$(Base.julia_exename()) -e 'print("no codegen!\n")'`) == "no codegen!"

# PR #47343
libs_emptied = 0
for f in libfiles
touch(joinpath(pfx, libpath, f))
libs_emptied += 1
end

errfile = joinpath(pfx, "stderr.txt")
@test libs_emptied > 0
@test_throws ProcessFailedException run(pipeline(`$pfx/bin/$(Base.julia_exename()) -e 'print("This should fail!\n")'`; stderr=errfile))
@test contains(readline(errfile), "ERROR: Unable to load dependent library")
end

# issue #42645
Expand Down

0 comments on commit 9f843b8

Please sign in to comment.