diff options
author | Dmitry Goncharov <dgoncharov@users.sf.net> | 2022-09-12 01:58:52 -0400 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2022-09-12 02:05:18 -0400 |
commit | ee861a4e9f523d06d26ed612ad1a93b6ecb408de (patch) | |
tree | 43e6d086d6d366bff448675c564ea85d60468c36 /src/load.c | |
parent | ca4234c4b550618df2194e0617c43bb12524f820 (diff) | |
download | make-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.c | 78 |
1 files changed, 36 insertions, 42 deletions
@@ -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"); |