Skip to content

Commit 9f843b8

Browse files
authored
make load_library() panic on some errors when err=0 (#47343)
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 #47027
1 parent bbdee0b commit 9f843b8

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

cli/loader_lib.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ extern "C" {
1313
/* Bring in helper functions for windows without libgcc. */
1414
#ifdef _OS_WINDOWS_
1515
#include "loader_win_utils.c"
16+
17+
#include <fileapi.h>
18+
static int win_file_exists(wchar_t* wpath) {
19+
return GetFileAttributesW(wpath) == INVALID_FILE_ATTRIBUTES ? 0 : 1;
20+
}
1621
#endif
1722

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

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

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

5769
#if defined(_OS_WINDOWS_)
70+
#define PATH_EXISTS() win_file_exists(wpath)
5871
wchar_t wpath[2*JL_PATH_MAX + 1] = {0};
5972
if (!utf8_to_wchar(path, wpath, 2*JL_PATH_MAX)) {
6073
jl_loader_print_stderr3("ERROR: Unable to convert path ", path, " to wide string!\n");
6174
exit(1);
6275
}
6376
handle = (void *)LoadLibraryExW(wpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
6477
#else
78+
#define PATH_EXISTS() !access(path, F_OK)
6579
handle = dlopen(path, RTLD_NOW | (err ? RTLD_GLOBAL : RTLD_LOCAL));
6680
#endif
67-
6881
if (handle == NULL) {
69-
if (!err)
82+
if (!err && !PATH_EXISTS())
7083
return NULL;
84+
#undef PATH_EXISTS
7185
jl_loader_print_stderr3("ERROR: Unable to load dependent library ", path, "\n");
7286
#if defined(_OS_WINDOWS_)
7387
LPWSTR wmsg = TEXT("");

test/compiler/codegen.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,12 +689,25 @@ mktempdir() do pfx
689689
cp(dirname(Sys.BINDIR), pfx; force=true)
690690
libpath = relpath(dirname(dlpath(libjulia_codegen_name())), dirname(Sys.BINDIR))
691691
libs_deleted = 0
692-
for f in filter(f -> startswith(f, "libjulia-codegen"), readdir(joinpath(pfx, libpath)))
692+
libfiles = filter(f -> startswith(f, "libjulia-codegen"), readdir(joinpath(pfx, libpath)))
693+
for f in libfiles
693694
rm(joinpath(pfx, libpath, f); force=true, recursive=true)
694695
libs_deleted += 1
695696
end
696697
@test libs_deleted > 0
697698
@test readchomp(`$pfx/bin/$(Base.julia_exename()) -e 'print("no codegen!\n")'`) == "no codegen!"
699+
700+
# PR #47343
701+
libs_emptied = 0
702+
for f in libfiles
703+
touch(joinpath(pfx, libpath, f))
704+
libs_emptied += 1
705+
end
706+
707+
errfile = joinpath(pfx, "stderr.txt")
708+
@test libs_emptied > 0
709+
@test_throws ProcessFailedException run(pipeline(`$pfx/bin/$(Base.julia_exename()) -e 'print("This should fail!\n")'`; stderr=errfile))
710+
@test contains(readline(errfile), "ERROR: Unable to load dependent library")
698711
end
699712

700713
# issue #42645

0 commit comments

Comments
 (0)