/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
+/* Extract the diagnostic strings from the error table macro in the same
+ order as the enumberated indices in ltdl.h. */
+
+static const char *lt_dlerror_strings[] =
+ {
+#define LT_ERROR(name, diagnostic) (diagnostic),
+ lt_dlerror_table
+#undef LT_ERROR
+
+ 0
+ };
+
/* This structure is used for the list of registered loaders. */
struct lt_dlloader {
struct lt_dlloader *next;
#define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
+#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
+
static const char objdir[] = LTDL_OBJDIR;
#ifdef LTDL_SHLIB_EXT
static const char shlib_ext[] = LTDL_SHLIB_EXT;
+\f
+/* --- MUTEX LOCKING --- */
+
+
+/* Macros to make it easier to run the lock functions only if they have
+ been registered. The reason for the complicated lock macro is to
+ ensure that the stored error message from the last error is not
+ accidentally erased if the current function doesn't generate an
+ error of its own. */
+#define MUTEX_LOCK() LT_STMT_START { \
+ if (mutex_lock) (*mutex_lock)(); } LT_STMT_END
+#define MUTEX_UNLOCK() LT_STMT_START { \
+ if (mutex_unlock) (*mutex_unlock)(); } LT_STMT_END
+#define MUTEX_SETERROR(errormsg) LT_STMT_START { \
+ if (mutex_seterror) (*mutex_seterror) (errormsg); \
+ else last_error = (errormsg); } LT_STMT_END
+#define MUTEX_GETERROR(errormsg) LT_STMT_START { \
+ if (mutex_seterror) errormsg = (*mutex_geterror)(); \
+ else (errormsg) = last_error; } LT_STMT_END
+
+/* The mutex functions stored here are global, and are necessarily the
+ same for all threads that wish to share access to libltdl. */
+static lt_dlmutex_lock *mutex_lock = 0;
+static lt_dlmutex_unlock *mutex_unlock = 0;
+static lt_dlmutex_seterror *mutex_seterror = 0;
+static lt_dlmutex_geterror *mutex_geterror = 0;
+static const char *last_error = 0;
+
+
+/* Either set or reset the mutex functions. Either all the arguments must
+ be valid functions, or else all can be NULL to turn off locking entirely.
+ The registered functions should be manipulating a static global lock
+ from the lock() and unlock() callbacks, which needs to be reentrant. */
+int
+lt_dlmutex_register (lock, unlock, seterror, geterror)
+ lt_dlmutex_lock *lock;
+ lt_dlmutex_unlock *unlock;
+ lt_dlmutex_seterror *seterror;
+ lt_dlmutex_geterror *geterror;
+{
+ lt_dlmutex_unlock *old_unlock = unlock;
+ int errors = 0;
+
+ /* Lock using the old lock() callback, if any. */
+ MUTEX_LOCK ();
+
+ if ((lock && unlock && seterror && geterror)
+ || !(lock || unlock || seterror || geterror))
+ {
+ mutex_lock = lock;
+ mutex_unlock = unlock;
+ mutex_geterror = geterror;
+ }
+ else
+ {
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
+ ++errors;
+ }
+
+ /* Use the old unlock() callback we saved earlier, if any. Otherwise
+ record any errors using internal storage. */
+ if (old_unlock)
+ (*old_unlock) ();
+
+ /* Return the number of errors encountered during the execution of
+ this function. */
+ return errors;
+}
+
+
+
\f
/* --- MEMORY HANDLING --- */
/* --- ERROR MESSAGES --- */
-/* Extract the diagnostic strings from the error table macro in the same
- order as the enumberated indices in ltdl.h. */
-
-static const char *lt_dlerror_strings[] =
- {
-#define LT_ERROR(name, diagnostic) (diagnostic),
- lt_dlerror_table
-#undef LT_ERROR
-
- 0
- };
-
-#define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
-
-static const char *last_error = 0;
static const char **user_error_strings = 0;
-static int errorcode = LT_ERROR_MAX;
+static int errorcount = LT_ERROR_MAX;
int
lt_dladderror (diagnostic)
const char *diagnostic;
{
- int index = errorcode - LT_ERROR_MAX;
- const char **temp = 0;
+ int index = 0;
+ int result = -1;
+ const char **temp = (const char **) 0;
+ MUTEX_LOCK ();
+
+ index = errorcount - LT_ERROR_MAX;
temp = LT_DLREALLOC (const char *, user_error_strings, 1 + index);
if (temp == 0)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
- return -1;
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
}
else
{
- user_error_strings = temp;
+ user_error_strings = temp;
+ user_error_strings[index] = diagnostic;
+ result = errorcount++;
}
- user_error_strings[index] = diagnostic;
+ MUTEX_UNLOCK ();
- return errorcode++;
+ return result;
}
int
lt_dlseterror (index)
int index;
{
- if (index >= errorcode || index < 0)
+ int errors = 0;
+
+ MUTEX_LOCK ();
+
+ if (index >= errorcount || index < 0)
{
- last_error = LT_DLSTRERROR (INVALID_ERRORCODE);
- return 1;
+ /* Ack! Error setting the error message! */
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
+ ++errors;
}
-
- if (index < LT_ERROR_MAX)
+ else if (index < LT_ERROR_MAX)
{
- last_error = lt_dlerror_strings[errorcode];
+ /* No error setting the error message! */
+ MUTEX_SETERROR (lt_dlerror_strings[errorcount]);
}
else
{
- last_error = user_error_strings[errorcode - LT_ERROR_MAX];
+ /* No error setting the error message! */
+ MUTEX_SETERROR (user_error_strings[errorcount - LT_ERROR_MAX]);
}
- return 0;
+ MUTEX_UNLOCK ();
+
+ return errors;
}
lt_user_data loader_data;
const char *filename;
{
- lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
+ lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
if (!module)
{
- last_error = DLERROR (CANNOT_OPEN);
+ MUTEX_SETERROR (DLERROR (CANNOT_OPEN));
}
return module;
lt_user_data loader_data;
lt_module module;
{
+ int errors = 0;
+
if (dlclose (module) != 0)
{
- last_error = DLERROR (CANNOT_CLOSE);
+ MUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
+ ++errors;
}
- return 0;
+ return errors;
}
static lt_ptr
if (!address)
{
- last_error = DLERROR (SYMBOL_NOT_FOUND);
+ MUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
}
return address;
if (!module)
{
- last_error = LT_DLSTRERROR (CANNOT_OPEN);
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
}
return module;
lt_user_data loader_data;
lt_module module;
{
+ int errors = 0;
+
if (shl_unload ((shl_t) (module)) != 0)
{
- last_error = LT_DLSTRERROR (CANNOT_CLOSE);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+ ++errors;
}
- return 0;
+ return errors;
}
static lt_ptr
return address;
}
- last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
}
return 0;
const char *filename;
{
lt_dlhandle cur;
- lt_module module;
+ lt_module module = 0;
+ const char *errormsg = 0;
char *searchname = 0;
char *ext;
char self_name_buf[MAX_PATH];
searchname = LT_DLMALLOC (char, 2+ strlen (filename));
if (!searchname)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 0;
}
strcpy (searchname, filename);
We check whether LoadLibrary is returning a handle to
an already loaded module, and simulate failure if we
find one. */
+ MUTEX_LOCK ();
cur = handles;
while (cur)
{
cur = cur->next;
}
+ MUTEX_UNLOCK ();
if (cur || !module)
{
- last_error = LT_DLSTRERROR (CANNOT_OPEN);
- return 0;
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
+ module = 0;
}
return module;
lt_user_data loader_data;
lt_module module;
{
+ int errors = 0;
+
if (FreeLibrary(module) == 0)
{
- last_error = LT_DLSTRERROR (CANNOT_CLOSE);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+ ++errors;
}
- return 0;
+ return errors;
}
static lt_ptr
lt_module module;
const char *symbol;
{
- lt_ptr address = GetProcAddress (module, symbol);
+ lt_ptr address = GetProcAddress (module, symbol);
if (!address)
{
- last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
}
return address;
if (image <= 0)
{
- last_error = LT_DLSTRERROR (CANNOT_OPEN);
- return 0;
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
+ image = 0;
}
return (lt_module) image;
lt_user_data loader_data;
lt_module module;
{
+ int errors = 0;
+
if (unload_add_on ((image_id) module) != B_OK)
{
- last_error = LT_DLSTRERROR (CANNOT_CLOSE);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+ ++errors;
}
- return 0;
+ return errors;
}
static lt_ptr
if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
{
- last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
- return 0;
+ MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
+ address = 0;
}
return address;
if (!module)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
- return 0;
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+ module = 0;
}
-
- if (dld_link (filename) != 0)
+ else if (dld_link (filename) != 0)
{
- last_error = LT_DLSTRERROR (CANNOT_OPEN);
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
LT_DLFREE (module);
- return 0;
+ module = 0;
}
return module;
lt_user_data loader_data;
lt_module module;
{
+ int errors = 0;
+
if (dld_unlink_by_file ((char*)(module), 1) != 0)
{
- last_error = LT_DLSTRERROR (CANNOT_CLOSE);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
+ ++errors;
+ }
+ else
+ {
+ LT_DLFREE (module);
}
- LT_DLFREE (module);
- return 0;
+ return errors;
}
static lt_ptr
if (!address)
{
- last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
}
return address;
presym_init (loader_data)
lt_user_data loader_data;
{
- preloaded_symbols = 0;
+ int errors = 0;
+
+ MUTEX_LOCK ();
+ preloaded_symbols = 0;
if (default_preloaded_symbols)
{
- return lt_dlpreload (default_preloaded_symbols);
+ errors = lt_dlpreload (default_preloaded_symbols);
}
- return 0;
+ MUTEX_UNLOCK ();
+
+ return errors;
}
static int
presym_free_symlists ()
{
- lt_dlsymlists_t *lists = preloaded_symbols;
+ lt_dlsymlists_t *lists;
+ MUTEX_LOCK ();
+
+ lists = preloaded_symbols;
while (lists)
{
lt_dlsymlists_t *tmp = lists;
}
preloaded_symbols = 0;
+ MUTEX_UNLOCK ();
+
return 0;
}
const lt_dlsymlist *preloaded;
{
lt_dlsymlists_t *tmp;
- lt_dlsymlists_t *lists = preloaded_symbols;
+ lt_dlsymlists_t *lists;
+ int errors = 0;
+ MUTEX_LOCK ();
+
+ lists = preloaded_symbols;
while (lists)
{
if (lists->syms == preloaded)
{
- return 0;
+ goto done;
}
lists = lists->next;
}
tmp = LT_DLMALLOC (lt_dlsymlists_t, 1);
- if (!tmp)
+ if (tmp)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
- return 1;
+ tmp->syms = preloaded;
+ tmp->next = preloaded_symbols;
+ preloaded_symbols = tmp;
+ }
+ else
+ {
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+ ++errors;
}
- tmp->syms = preloaded;
- tmp->next = preloaded_symbols;
- preloaded_symbols = tmp;
- return 0;
+ done:
+ MUTEX_UNLOCK ();
+ return errors;
}
static lt_module
lt_user_data loader_data;
const char *filename;
{
- lt_dlsymlists_t *lists = preloaded_symbols;
+ lt_dlsymlists_t *lists;
+ lt_module module = (lt_module) 0;
+
+ MUTEX_LOCK ();
+ lists = preloaded_symbols;
if (!lists)
{
- last_error = LT_DLSTRERROR (NO_SYMBOLS);
- return 0;
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
+ goto done;
}
if (!filename)
{
if (!syms->address && strcmp(syms->name, filename) == 0)
{
- return (lt_module) syms;
+ module = (lt_module) syms;
+ goto done;
}
++syms;
}
lists = lists->next;
}
- last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
- return 0;
+ done:
+ MUTEX_UNLOCK ();
+ return module;
}
static int
++syms;
}
- last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
return 0;
}
static lt_dlhandle handles = 0;
static int initialized = 0;
+/* Initialize libltdl. */
int
lt_dlinit ()
{
- /* initialize libltdl */
- int errors = 0;
+ int errors = 0;
+
+ MUTEX_LOCK ();
/* Initialize only at first call. */
if (++initialized == 1)
if (presym_init (presym.dlloader_data))
{
- last_error = LT_DLSTRERROR (INIT_LOADER);
+ MUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
++errors;
}
else if (errors != 0)
{
- last_error = LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED);
+ MUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
++errors;
}
- else
- {
- last_error = 0;
- }
}
+ MUTEX_UNLOCK ();
+
return errors;
}
lt_dlpreload (preloaded)
const lt_dlsymlist *preloaded;
{
+ int errors = 0;
+
if (preloaded)
{
- return presym_add_symlist (preloaded);
+ errors = presym_add_symlist (preloaded);
}
-
- presym_free_symlists();
- if (default_preloaded_symbols)
+ else
{
- return lt_dlpreload (default_preloaded_symbols);
+ const char *errormsg = 0;
+
+ presym_free_symlists();
+
+ MUTEX_LOCK ();
+ if (default_preloaded_symbols)
+ {
+ errors = lt_dlpreload (default_preloaded_symbols);
+ }
+ MUTEX_UNLOCK ();
}
- return 0;
+ return errors;
}
int
lt_dlpreload_default (preloaded)
const lt_dlsymlist *preloaded;
{
+ MUTEX_LOCK ();
default_preloaded_symbols = preloaded;
+ MUTEX_UNLOCK ();
return 0;
}
lt_dlexit ()
{
/* shut down libltdl */
- lt_dlloader *loader = loaders;
- int errors = 0;
+ lt_dlloader *loader;
+ const char *errormsg;
+ int errors = 0;
+
+ MUTEX_LOCK ();
+ loader = loaders;
if (!initialized)
{
- last_error = LT_DLSTRERROR (SHUTDOWN);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
+ ++errors;
+ goto done;
}
/* shut down only at last call. */
loaders = 0;
}
+ done:
+ MUTEX_UNLOCK ();
return errors;
}
lt_dlhandle *handle;
const char *filename;
{
- lt_dlhandle cur = handles;
- lt_dlloader *loader = loaders;
- const char *saved_error = last_error;
+ lt_dlhandle cur;
+ lt_dlloader *loader;
+ const char *saved_error;
+ int errors = 0;
+
+ MUTEX_GETERROR (saved_error);
+ MUTEX_LOCK ();
+
+ cur = handles;
+ loader = loaders;
/* check whether the module was already opened */
while (cur)
{
++cur->info.ref_count;
*handle = cur;
- return 0;
+ goto done;
}
cur = *handle;
cur->info.filename = strdup (filename);
if (!cur->info.filename)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+ ++errors;
+ goto done;
}
}
else
if (!loader)
{
LT_DLFREE (cur->info.filename);
- return 1;
+ ++errors;
+ goto done;
}
cur->loader = loader;
last_error = saved_error;
+
+ done:
+ MUTEX_UNLOCK ();
- return 0;
+ return errors;
}
static int
if (!filename)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 1;
}
if (!filename)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 1;
}
char **pdir;
lt_dlhandle *handle;
{
- /* when handle != NULL search a library, otherwise a file */
- /* return NULL on failure, otherwise the file/handle */
+ /* When handle != NULL search a library, otherwise a file
+ return NULL on failure, otherwise the file/handle. */
lt_ptr result = 0;
char *filename = 0;
char *canonical = 0;
char *next = 0;
+ MUTEX_LOCK ();
+
if (!search_path || !*search_path)
{
- last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
- return 0;
+ MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
+ goto cleanup;
}
canonical = canonicalize_path (search_path);
if (!canonical)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
goto cleanup;
}
if (!filename)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
goto cleanup;
}
}
}
}
- last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
cleanup:
LT_DLFREE (filename);
LT_DLFREE (canonical);
+ MUTEX_UNLOCK ();
+
return result;
}
int i;
char **names = 0;
#endif
- int ret = 0;
+ int errors = 0;
handle->depcount = 0;
#if LTDL_DLOPEN_DEPLIBS
- ret = 1;
if (!deplibs)
{
- return 0;
+ return errors;
}
+ ++errors;
+ MUTEX_LOCK ();
save_search_path = strdup (user_search_path);
if (user_search_path && !save_search_path)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+ goto cleanup;
}
/* extract search paths and count deplibs */
}
}
+ /* restore the old search path */
+ LT_DLFREE (user_search_path);
+ user_search_path = save_search_path;
+
+ MUTEX_UNLOCK ();
+
if (!depcount)
{
- ret = 0;
+ errors = 0;
goto cleanup;
}
}
handle->depcount = j; /* Number of successfully loaded deplibs */
- ret = 0;
+ errors = 0;
}
cleanup_names:
cleanup:
LT_DLFREE (names);
-
- /* restore the old search path */
- LT_DLFREE (user_search_path);
- user_search_path = save_search_path;
#endif
- return ret;
+ return errors;
}
static int
{
lt_dlhandle handle = 0, newhandle;
const char *ext;
- const char *saved_error = last_error;
+ const char *saved_error;
char *canonical = 0, *basename = 0, *dir = 0, *name = 0;
+ MUTEX_GETERROR (saved_error);
+
/* dlopen self? */
if (!filename)
{
handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 0;
}
canonical = canonicalize_path (filename);
if (!canonical)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
LT_DLFREE (handle);
return 0;
}
dir = LT_DLMALLOC (char, basename - canonical + 1);
if (!dir)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
handle = 0;
goto cleanup;
}
basename = canonical;
}
- /* check whether we open a libtool module (.la extension) */
+ /* Check whether we are opening a libtool module (.la extension). */
ext = strrchr(basename, '.');
if (ext && strcmp(ext, ".la") == 0)
{
of libtool */
int installed = 1;
- /* extract the module name from the file name */
- name = LT_DLMALLOC (char, ext - basename + 1);
- if (!name)
- {
- last_error = LT_DLSTRERROR (NO_MEMORY);
- handle = 0;
- goto cleanup;
+ /* extract the module name from the file name */
+ name = LT_DLMALLOC (char, ext - basename + 1);
+ if (!name)
+ {
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+ handle = 0;
+ goto cleanup;
}
/* canonicalize the module name */
}
if (!file)
{
- last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
}
if (!file)
if (!line)
{
fclose (file);
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
handle = 0;
goto cleanup;
}
LT_DLFREE (handle);
if (!error)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
}
free_vars (dlname, old_name, libdir, deplibs);
handle = (lt_dlhandle) LT_DLMALLOC (struct lt_dlhandle_struct, 1);
if (!handle)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
/* handle is already set to 0 */
goto cleanup;
}
handle->info.ref_count = 1;
handle->info.name = name;
handle->next = handles;
+
+ MUTEX_LOCK ();
handles = handle;
+ MUTEX_UNLOCK ();
name = 0; /* don't free this during `cleanup' */
}
- last_error = saved_error;
+
+ MUTEX_SETERROR (saved_error);
cleanup:
LT_DLFREE (dir);
lt_dlhandle handle;
char *tmp;
int len;
- const char *saved_error = last_error;
+ const char *saved_error;
+
+ MUTEX_GETERROR (saved_error);
if (!filename)
{
len = strlen (filename);
if (!len)
{
- last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
return 0;
}
tmp = LT_DLMALLOC (char, len+4);
if (!tmp)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 0;
}
strcpy (tmp, filename);
handle = lt_dlopen (tmp);
if (handle)
{
- last_error = saved_error;
+ MUTEX_SETERROR (saved_error);
LT_DLFREE (tmp);
return handle;
}
tmp = LT_DLMALLOC (char, len + strlen (shlib_ext) + 1);
if (!tmp)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 0;
}
strcpy (tmp, filename);
handle = lt_dlopen (tmp);
if (handle)
{
- last_error = saved_error;
+ MUTEX_SETERROR (saved_error);
LT_DLFREE (tmp);
return handle;
}
return handle;
}
- last_error = LT_DLSTRERROR (FILE_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
LT_DLFREE (tmp);
return 0;
}
lt_dlhandle handle;
{
lt_dlhandle cur, last;
+ int errors = 0;
+
+ MUTEX_LOCK ();
/* check whether the handle is valid */
last = cur = handles;
if (!cur)
{
- last_error = LT_DLSTRERROR (INVALID_HANDLE);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+ ++errors;
+ goto done;
}
handle->info.ref_count--;
moment). */
if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
{
- int error;
lt_user_data data = handle->loader->dlloader_data;
if (handle != handles)
handles = handle->next;
}
- error = handle->loader->module_close (data, handle->module);
- error += unload_deplibs(handle);
+ errors += handle->loader->module_close (data, handle->module);
+ errors += unload_deplibs(handle);
LT_DLFREE (handle->info.filename);
LT_DLFREE (handle->info.name);
-
LT_DLFREE (handle);
- return error;
+ goto done;
}
if (LT_DLIS_RESIDENT (handle))
{
- last_error = LT_DLSTRERROR (CLOSE_RESIDENT_MODULE);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
+ ++errors;
}
- return 0;
+ done:
+ MUTEX_UNLOCK ();
+
+ return errors;
}
lt_ptr
if (!handle)
{
- last_error = LT_DLSTRERROR (INVALID_HANDLE);
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
return 0;
}
if (!symbol)
{
- last_error = LT_DLSTRERROR (SYMBOL_NOT_FOUND);
+ MUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
return 0;
}
if (!sym)
{
- last_error = LT_DLSTRERROR (BUFFER_OVERFLOW);
+ MUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
return 0;
}
data = handle->loader->dlloader_data;
if (handle->info.name)
{
- const char *saved_error = last_error;
+ const char *saved_error;
+
+ MUTEX_GETERROR (saved_error);
/* this is a libtool module */
if (handle->loader->sym_prefix)
}
return address;
}
- last_error = saved_error;
+ MUTEX_SETERROR (saved_error);
}
/* otherwise try "symbol" */
const char *
lt_dlerror ()
{
- const char *error = last_error;
+ const char *error;
+
+ MUTEX_GETERROR (error);
+ MUTEX_SETERROR (0);
- last_error = 0;
return error;
}
lt_dladdsearchdir (search_dir)
const char *search_dir;
{
+ int errors = 0;
+
if (!search_dir || !strlen(search_dir))
{
- return 0;
+ return errors;
}
+ MUTEX_LOCK ();
if (!user_search_path)
{
user_search_path = strdup (search_dir);
if (!user_search_path)
{
last_error = LT_DLSTRERROR (NO_MEMORY);
- return 1;
+ ++errors;
}
}
else
if (!new_search_path)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+ ++errors;
}
+ else
+ {
+ sprintf (new_search_path, "%s%c%s", user_search_path,
+ LT_PATHSEP_CHAR, search_dir);
- sprintf (new_search_path, "%s%c%s", user_search_path,
- LT_PATHSEP_CHAR, search_dir);
-
- LT_DLMEM_REASSIGN (user_search_path, new_search_path);
+ LT_DLMEM_REASSIGN (user_search_path, new_search_path);
+ }
}
+ MUTEX_UNLOCK ();
- return 0;
+ return errors;
}
int
lt_dlsetsearchpath (search_path)
const char *search_path;
{
+ int errors = 0;
+
+ MUTEX_LOCK ();
LT_DLFREE (user_search_path);
+ MUTEX_UNLOCK ();
if (!search_path || !strlen (search_path))
{
- return 0;
+ return errors;
}
+ MUTEX_LOCK ();
user_search_path = strdup (search_path);
if (!user_search_path)
{
- return 1;
+ ++errors;
}
+ MUTEX_UNLOCK ();
- return 0;
+ return errors;
}
const char *
lt_dlgetsearchpath ()
{
- return user_search_path;
+ const char *saved_path;
+
+ MUTEX_LOCK ();
+ saved_path = user_search_path;
+ MUTEX_UNLOCK ();
+
+ return saved_path;
}
int
lt_dlmakeresident (handle)
lt_dlhandle handle;
{
+ int errors = 0;
+
if (!handle)
{
- last_error = LT_DLSTRERROR (INVALID_HANDLE);
- return -1;
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
+ ++errors;
+ }
+ else
+ {
+ LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
}
- LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
-
- return 0;
+ return errors;
}
int
{
if (!handle)
{
- last_error = LT_DLSTRERROR (INVALID_HANDLE);
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
return -1;
}
{
if (!handle)
{
- last_error = LT_DLSTRERROR (INVALID_HANDLE);
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
return 0;
}
int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
lt_ptr data;
{
- lt_dlhandle cur = handles;
+ int errors = 0;
+ lt_dlhandle cur;
+ MUTEX_LOCK ();
+
+ cur = handles;
while (cur)
{
lt_dlhandle tmp = cur;
cur = cur->next;
if ((*func) (tmp, data))
{
- return 1;
+ ++errors;
+ break;
}
}
- return 0;
+ MUTEX_UNLOCK ();
+
+ return errors;
}
lt_dlcaller_id
lt_dlcaller_register ()
{
static int last_caller_id = -1;
+ int result;
- return ++last_caller_id;
+ MUTEX_LOCK ();
+ result = ++last_caller_id;
+ MUTEX_UNLOCK ();
+
+ return result;
}
#define N_ELEMENTS(a) (sizeof(a) / sizeof(*(a)))
lt_ptr stale = (lt_ptr) 0;
int i;
+ /* This needs to be locked so that the caller data can be updated
+ simultaneously by different threads. */
+ MUTEX_LOCK ();
+
if (handle->caller_data)
n_elements = N_ELEMENTS (handle->caller_data);
if (temp == 0)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
- return (lt_ptr) 0;
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
+ stale = (lt_ptr) 0;
+ goto done;
}
else
{
handle->caller_data[i].data = data;
+ done:
+ MUTEX_UNLOCK ();
+
return stale;
}
lt_ptr result = (lt_ptr) 0;
int n_elements = 0;
+ /* This needs to be locked so that the caller data isn't updated by
+ another thread part way through this function. */
+ MUTEX_LOCK ();
+
if (handle->caller_data)
n_elements = N_ELEMENTS (handle->caller_data);
}
}
+ MUTEX_UNLOCK ();
+
return result;
}
const struct lt_user_dlloader *dlloader;
const char *loader_name;
{
+ int errors = 0;
lt_dlloader *node = 0, *ptr = 0;
if ((dlloader == 0) /* diagnose null parameters */
|| (dlloader->module_close == 0)
|| (dlloader->find_sym == 0))
{
- last_error = LT_DLSTRERROR (INVALID_LOADER);
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
return 1;
}
node = LT_DLMALLOC (lt_dlloader, 1);
if (node == 0)
{
- last_error = LT_DLSTRERROR (NO_MEMORY);
+ MUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
return 1;
}
+
node->next = 0;
node->loader_name = loader_name;
node->sym_prefix = dlloader->sym_prefix;
node->find_sym = dlloader->find_sym;
node->dlloader_data = dlloader->dlloader_data;
+ MUTEX_LOCK ();
if (!loaders)
{
/* If there are no loaders, NODE becomes the list! */
if (ptr->next != place)
{
last_error = LT_DLSTRERROR (INVALID_LOADER);
- return 1;
+ ++errors;
+ }
+ else
+ {
+ /* Insert NODE between PTR and PLACE. */
+ node->next = place;
+ ptr->next = node;
}
-
- /* Insert NODE between PTR and PLACE. */
- node->next = place;
- ptr->next = node;
}
- return 0;
+ MUTEX_UNLOCK ();
+
+ return errors;
}
int
{
lt_dlloader *place = lt_dlloader_find (loader_name);
lt_dlhandle handle;
- int result = 0;
+ int errors = 0;
if (!place)
{
- last_error = LT_DLSTRERROR (INVALID_LOADER);
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
return 1;
}
+ MUTEX_LOCK ();
+
/* Fail if there are any open modules which use this loader. */
for (handle = handles; handle; handle = handle->next)
{
if (handle->loader == place)
{
- last_error = LT_DLSTRERROR (REMOVE_LOADER);
- return 1;
+ MUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
+ ++errors;
+ goto done;
}
}
if (place->dlloader_exit)
{
- result = place->dlloader_exit (place->dlloader_data);
+ errors = place->dlloader_exit (place->dlloader_data);
}
LT_DLFREE (place);
- return result;
+ done:
+ MUTEX_UNLOCK ();
+
+ return errors;
}
lt_dlloader *
lt_dlloader_next (place)
lt_dlloader *place;
{
- return place ? place->next : loaders;
+ lt_dlloader *next;
+
+ MUTEX_LOCK ();
+ next = place ? place->next : loaders;
+ MUTEX_UNLOCK ();
+
+ return next;
}
const char *
lt_dlloader_name (place)
lt_dlloader *place;
{
- if (!place)
+ const char *name = 0;
+
+ if (place)
{
- last_error = LT_DLSTRERROR (INVALID_LOADER);
+ MUTEX_LOCK ();
+ name = place ? place->loader_name : 0;
+ MUTEX_UNLOCK ();
+ }
+ else
+ {
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
}
- return place ? place->loader_name : 0;
+ return name;
}
lt_user_data *
lt_dlloader_data (place)
lt_dlloader *place;
{
- if (!place)
+ lt_user_data *data = 0;
+
+ if (place)
+ {
+ MUTEX_LOCK ();
+ data = place ? &(place->dlloader_data) : 0;
+ MUTEX_UNLOCK ();
+ }
+ else
{
- last_error = LT_DLSTRERROR (INVALID_LOADER);
+ MUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
}
- return place ? &(place->dlloader_data) : 0;
+ return data;
}
lt_dlloader *
{
lt_dlloader *place = 0;
+ MUTEX_LOCK ();
for (place = loaders; place; place = place->next)
{
if (strcmp (place->loader_name, loader_name) == 0)
break;
}
}
+ MUTEX_UNLOCK ();
return place;
}