diff --git a/src/c/alloc_2.d b/src/c/alloc_2.d index adb4b655b..00aeb3d3c 100644 --- a/src/c/alloc_2.d +++ b/src/c/alloc_2.d @@ -487,6 +487,7 @@ cl_object_mark_proc(void *addr, struct GC_ms_entry *msp, struct GC_ms_entry *msl break; # endif case t_codeblock: + MAYBE_MARK(o->cblock.error); MAYBE_MARK(o->cblock.source); MAYBE_MARK(o->cblock.links); MAYBE_MARK(o->cblock.name); @@ -1037,7 +1038,8 @@ init_alloc(void) to_bitmap(&o, &(o.cblock.next)) | to_bitmap(&o, &(o.cblock.name)) | to_bitmap(&o, &(o.cblock.links)) | - to_bitmap(&o, &(o.cblock.source)); + to_bitmap(&o, &(o.cblock.source)) | + to_bitmap(&o, &(o.cblock.error)); type_info[t_foreign].descriptor = to_bitmap(&o, &(o.foreign.data)) | to_bitmap(&o, &(o.foreign.tag)); diff --git a/src/c/ffi.d b/src/c/ffi.d index bcca92ec1..c9934bc47 100644 --- a/src/c/ffi.d +++ b/src/c/ffi.d @@ -709,8 +709,9 @@ si_load_foreign_module(cl_object filename) # endif output = ecl_library_open(filename, 0); if (output->cblock.handle == NULL) { + cl_object aux = ecl_library_error(output); ecl_library_close(output); - output = ecl_library_error(output); + output = aux; } # ifdef ECL_THREADS (void)0; /* MSVC complains about missing ';' before '}' */ diff --git a/src/c/ffi/libraries.d b/src/c/ffi/libraries.d index 7382f119a..56ffc0f84 100644 --- a/src/c/ffi/libraries.d +++ b/src/c/ffi/libraries.d @@ -144,6 +144,37 @@ copy_object_file(cl_object original) } #ifdef ENABLE_DLOPEN + +static void +set_library_error(cl_object block) { + cl_object output; + ecl_disable_interrupts(); +#ifdef HAVE_DLFCN_H + output = make_base_string_copy(dlerror()); +#endif +#ifdef HAVE_MACH_O_DYLD_H + { + NSLinkEditErrors c; + int number; + const char *filename; + NSLinkEditError(&c, &number, &filename, &message); + output = make_base_string_copy(message); + } +#endif +#if defined(ECL_MS_WINDOWS_HOST) + { + const char *message; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER, + 0, GetLastError(), 0, (void*)&message, 0, NULL); + output = make_base_string_copy(message); + LocalFree(message); + } +#endif + ecl_enable_interrupts(); + block->cblock.source = output; +} + static void dlopen_wrapper(cl_object block) { @@ -170,6 +201,8 @@ dlopen_wrapper(cl_object block) #if defined(ECL_MS_WINDOWS_HOST) block->cblock.handle = LoadLibrary(filename_string); #endif + if (block->cblock.handle == NULL) + set_library_error(block); } static void @@ -390,37 +423,17 @@ ecl_library_symbol(cl_object block, const char *symbol, bool lock) { block->cblock.locked |= lock; } } + if (!p) + set_library_error(block); return p; } cl_object ecl_library_error(cl_object block) { - cl_object output; - ecl_disable_interrupts(); -#ifdef HAVE_DLFCN_H - output = make_base_string_copy(dlerror()); -#endif -#ifdef HAVE_MACH_O_DYLD_H - { - NSLinkEditErrors c; - int number; - const char *filename; - NSLinkEditError(&c, &number, &filename, &message); - output = make_base_string_copy(message); - } -#endif -#if defined(ECL_MS_WINDOWS_HOST) - { - const char *message; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_ALLOCATE_BUFFER, - 0, GetLastError(), 0, (void*)&message, 0, NULL); - output = make_base_string_copy(message); - LocalFree(message); - } -#endif - ecl_enable_interrupts(); - return output; + if (block->cblock.handle) + return block->cblock.error; + else + return ECL_NIL; } void diff --git a/src/h/object.h b/src/h/object.h index 76db4465f..acdb92cff 100644 --- a/src/h/object.h +++ b/src/h/object.h @@ -700,6 +700,7 @@ struct ecl_codeblock { const struct ecl_cfun *cfuns; cl_object source; /* common debug information for this block */ cl_object refs; /* reference counter for the library */ + cl_object error; /* error message when loading */ }; struct ecl_bytecodes {