summaryrefslogtreecommitdiff
path: root/src/load.c
diff options
context:
space:
mode:
authorDmitry Goncharov <dgoncharov@users.sf.net>2022-09-12 01:58:52 -0400
committerPaul Smith <psmith@gnu.org>2022-09-12 02:05:18 -0400
commitee861a4e9f523d06d26ed612ad1a93b6ecb408de (patch)
tree43e6d086d6d366bff448675c564ea85d60468c36 /src/load.c
parentca4234c4b550618df2194e0617c43bb12524f820 (diff)
downloadmake-git-ee861a4e9f523d06d26ed612ad1a93b6ecb408de.tar.gz
[SV 63045] Reload each intact unloaded shared object
If makefile rules do not update an unloaded shared object, load it again. Avoid double loading of the same object if the setup function returns -1. * src/filedef.h (struct file): Add "unloaded" flag. * src/makeint.h (load_file): Take struct file *. (unload_file): Return int. * src/main.c (main): Reload unloaded shared objects if they weren't updated. * src/commands.c (execute_file_commands): Set "unloaded" and reset "loaded" when a shared object is unloaded. * src/read.c (eval): Set "loaded" and reset "unloaded" when a shared object is loaded. Add successfully loaded files to the db. * src/load.c (load_file): Check "loaded" to avoid double loading the same object. Fix a memory leak of string loaded. Return -1, rather than 1, if the object is already loaded. This fixes double loading of the same object when the setup routine returns -1. (load_object): Add a log message. (unload_file): Return an error on dlclose failure. Log a message. * tests/scripts/features/loadapi: Add new tests.
Diffstat (limited to 'src/load.c')
-rw-r--r--src/load.c78
1 files changed, 36 insertions, 42 deletions
diff --git a/src/load.c b/src/load.c
index 701ca4da..81cc3011 100644
--- a/src/load.c
+++ b/src/load.c
@@ -90,6 +90,8 @@ load_object (const floc *flocp, int noerror, const char *ldname,
return NULL;
}
+ DB (DB_VERBOSE, (_("Loaded shared object %s\n"), ldname));
+
/* Assert that the GPL license symbol is defined. */
symp = (load_func_t) dlsym (dlp, "plugin_is_GPL_compatible");
if (! symp)
@@ -119,19 +121,19 @@ load_object (const floc *flocp, int noerror, const char *ldname,
}
int
-load_file (const floc *flocp, const char **ldname, int noerror)
+load_file (const floc *flocp, struct file *file, int noerror)
{
- size_t nmlen = strlen (*ldname);
+ const char *ldname = file->name;
+ size_t nmlen = strlen (ldname);
char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1);
char *symname = NULL;
- char *loaded;
const char *fp;
int r;
load_func_t symp;
/* Break the input into an object file name and a symbol name. If no symbol
name was provided, compute one from the object file name. */
- fp = strchr (*ldname, '(');
+ fp = strchr (ldname, '(');
if (fp)
{
const char *ep;
@@ -142,16 +144,16 @@ load_file (const floc *flocp, const char **ldname, int noerror)
ep = strchr (fp+1, ')');
if (ep && ep[1] == '\0')
{
- size_t l = fp - *ldname;;
+ size_t l = fp - ldname;
++fp;
if (fp == ep)
- OS (fatal, flocp, _("Empty symbol name for load: %s"), *ldname);
+ OS (fatal, flocp, _("Empty symbol name for load: %s"), ldname);
/* Make a copy of the ldname part. */
- memcpy (new, *ldname, l);
+ memcpy (new, ldname, l);
new[l] = '\0';
- *ldname = new;
+ ldname = new;
nmlen = l;
/* Make a copy of the symbol name part. */
@@ -161,22 +163,22 @@ load_file (const floc *flocp, const char **ldname, int noerror)
}
}
- /* Add this name to the string cache so it can be reused later. */
- *ldname = strcache_add (*ldname);
+ /* Make sure this name is in the string cache. */
+ ldname = file->name = strcache_add (ldname);
- /* If this object has been loaded, we're done. */
- loaded = allocated_variable_expand ("$(.LOADED)");
- fp = strstr (loaded, *ldname);
- r = fp && (fp==loaded || fp[-1]==' ') && (fp[nmlen]=='\0' || fp[nmlen]==' ');
- if (r)
- goto exit;
+ /* If this object has been loaded, we're done: return -1 to ensure make does
+ not rebuild again. If a rebuild is allowed it was set up when this
+ object was initially loaded. */
+ file = lookup_file (ldname);
+ if (file && file->loaded)
+ return -1;
/* If we didn't find a symbol name yet, construct it from the ldname. */
if (! symname)
{
char *p = new;
- fp = strrchr (*ldname, '/');
+ fp = strrchr (ldname, '/');
#ifdef HAVE_DOS_PATHS
if (fp)
{
@@ -186,13 +188,13 @@ load_file (const floc *flocp, const char **ldname, int noerror)
fp = fp2;
}
else
- fp = strrchr (*ldname, '\\');
+ fp = strrchr (ldname, '\\');
/* The (improbable) case of d:foo. */
if (fp && *fp && fp[1] == ':')
fp++;
#endif
if (!fp)
- fp = *ldname;
+ fp = ldname;
else
++fp;
while (isalnum ((unsigned char) *fp) || *fp == '_')
@@ -201,56 +203,48 @@ load_file (const floc *flocp, const char **ldname, int noerror)
symname = new;
}
- DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, *ldname));
+ DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, ldname));
/* Load it! */
- symp = load_object (flocp, noerror, *ldname, symname);
+ symp = load_object (flocp, noerror, ldname, symname);
if (! symp)
return 0;
/* Invoke the symbol. */
r = (*symp) (flocp);
- /* If it succeeded, add the load file to the loaded variable.
- Anything other than 0, including -1, is a success. */
+ /* If the load didn't fail, add the file to the .LOADED variable. */
if (r)
- {
- size_t loadlen = strlen (loaded);
- char *newval = alloca (loadlen + strlen (*ldname) + 2);
- /* Don't add a space if it's empty. */
- if (loadlen)
- {
- memcpy (newval, loaded, loadlen);
- newval[loadlen++] = ' ';
- }
- strcpy (&newval[loadlen], *ldname);
- do_variable_definition (flocp, ".LOADED", newval, o_default, f_simple, 0);
- }
+ do_variable_definition(flocp, ".LOADED", ldname, o_file, f_append_value, 0);
- exit:
- free (loaded);
return r;
}
-void
+int
unload_file (const char *name)
{
+ int rc = 0;
struct load_list *d;
for (d = loaded_syms; d != NULL; d = d->next)
if (streq (d->name, name) && d->dlp)
{
- if (dlclose (d->dlp))
+ DB (DB_VERBOSE, (_("Unloading shared object %s\n"), name));
+ rc = dlclose (d->dlp);
+ if (rc)
perror_with_name ("dlclose: ", d->name);
- d->dlp = NULL;
+ else
+ d->dlp = NULL;
break;
}
+
+ return rc;
}
#else
int
-load_file (const floc *flocp, const char **ldname UNUSED, int noerror)
+load_file (const floc *flocp, struct file *file UNUSED, int noerror)
{
if (! noerror)
O (fatal, flocp,
@@ -259,7 +253,7 @@ load_file (const floc *flocp, const char **ldname UNUSED, int noerror)
return 0;
}
-void
+int
unload_file (const char *name UNUSED)
{
O (fatal, NILF, "INTERNAL: Cannot unload when load is not supported");