Skip to content

Commit

Permalink
Improve dlerror message reporting
Browse files Browse the repository at this point in the history
- for absolute paths, show the error message if file exists.
  this way users always get diagnostics when they try a known
  path.
- for DL_LOAD_PATH/DL_EXT permutations: if a file exists, show
  error. these paths should be complete by construction (ie,
  include extension). if dlopen fails and the file exists,
  best to let the user know.
- when throwing an error, first print the dlerror, then free the
  handle, then throw the error. this is not idea, but is the
  simplest way I can think of to actually show the error without
  leaking the errmsg.
- free the handle before throwing an error on Windows

also add some comments.
  • Loading branch information
ihnorton committed May 29, 2015
1 parent 0cde1c0 commit 0c17fd3
Showing 1 changed file with 34 additions and 10 deletions.
44 changes: 34 additions & 10 deletions src/dlload.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,45 @@ static uv_lib_t *jl_load_dynamic_library_(const char *modname, unsigned flags, i
char *ext;
char path[PATHBUF];
int i;
uv_stat_t stbuf;
uv_lib_t *handle = (uv_lib_t*)malloc(sizeof(uv_lib_t));
handle->errmsg = NULL;

/*
this branch returns handle of libjulia
*/
if (modname == NULL) {
#ifdef _OS_WINDOWS_
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCWSTR)(&jl_load_dynamic_library),
&handle->handle))
&handle->handle)) {
free(handle);
jl_errorf("could not load base module", modname);
}
#else
handle->handle = dlopen(NULL,RTLD_NOW);
#endif
goto done;
}
/*
this branch shortcuts absolute paths
*/
#ifdef _OS_WINDOWS_
else if (modname[1] == ':') {
#else
else if (modname[0] == '/') {
#endif
error = jl_uv_dlopen(modname,handle,flags);
if (!error) goto done;
// bail out and show the error if file actually exists
if (jl_stat(modname, (char*)&stbuf) == 0) goto notfound;
if (handle->errmsg)
uv_dlclose(handle);
}
/*
this branch permutes all base paths in DL_LOAD_PATH with all extensions
note: skip when !jl_base_module to avoid UndefVarError(:DL_LOAD_PATH)
*/
else if (jl_base_module != NULL) {
jl_array_t *DL_LOAD_PATH = (jl_array_t*)jl_get_global(jl_base_module, jl_symbol("DL_LOAD_PATH"));
if (DL_LOAD_PATH != NULL) {
Expand All @@ -123,19 +140,26 @@ static uv_lib_t *jl_load_dynamic_library_(const char *modname, unsigned flags, i
else
snprintf(path, PATHBUF, "%s" PATHSEPSTRING "%s%s", dl_path, modname, ext);
if (handle->errmsg) {
// free handle->errmsg, else it will leak on next uv_dlopen
uv_dlclose(handle);
}

error = jl_uv_dlopen(path, handle, flags);
if (!error) goto done;
// bail out and show the error if file actually exists
if (jl_stat(path, (char*)&stbuf) == 0) goto notfound;
}
}
}
}

/*
now fall back and look in default library paths, for all extensions
*/
for(i=0; i < N_EXTENSIONS; i++) {
ext = extensions[i];
path[0] = '\0';
handle->handle = NULL;
/* try loading from standard library path */
snprintf(path, PATHBUF, "%s%s", modname, ext);
if (handle->errmsg) {
uv_dlclose(handle);
Expand All @@ -145,23 +169,23 @@ static uv_lib_t *jl_load_dynamic_library_(const char *modname, unsigned flags, i
}

#if defined(__linux__) || defined(__FreeBSD__)
// check map of versioned libs from "libX" to full soname "libX.so.ver"
{
const char *soname = jl_lookup_soname(modname, strlen(modname));
if (handle->errmsg) {
free(handle->errmsg);
handle->errmsg = NULL;
}
error = (soname==NULL) || jl_uv_dlopen(soname, handle, flags);
if (!error) goto done;
}
#endif

if (throw_err) {
//jl_printf(JL_STDERR, "could not load module %s (%d): %s\n", modname, error, uv_dlerror(handle));
jl_errorf("could not load module %s: %s", modname, uv_dlerror(handle));
}
notfound:
if (throw_err)
jl_printf(JL_STDERR, "dlerror loading '%s': %s\n", modname, uv_dlerror(handle));

uv_dlclose(handle);
free(handle);

if (throw_err)
jl_errorf("could not load library %s", modname);
return NULL;
done:
return handle;
Expand Down

0 comments on commit 0c17fd3

Please sign in to comment.