From 8a931a97b8dd19a38d6f719f810280a07ba76438 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Wed, 19 Aug 2020 15:26:42 +0200 Subject: [PATCH] Fix native code uneffective loads after recompilation 'dlopen' can return the same handle if two shared with the same filename are loaded in two different times (even if the first was deleted!). To prevent this scenario the last modification time of the source file is included in the hashing algorithm. * src/comp.c (Fcomp_el_to_eln_filename): Update hashing algo to include the source last modification date. * src/lread.c (maybe_swap_for_eln): Do not check for eln newer then elc as this is now unnecessary. --- src/comp.c | 19 +++++++++++++++++-- src/lread.c | 20 +++++++------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/comp.c b/src/comp.c index ff73245b8de..a00088bb7f8 100644 --- a/src/comp.c +++ b/src/comp.c @@ -3872,13 +3872,26 @@ If BASE-DIR is nil use the first entry in `comp-eln-load-path'. */) { CHECK_STRING (filename); + if (NILP (Ffile_exists_p (filename))) + xsignal1 (Qfile_missing, filename); + + Lisp_Object last_mod_time = + Fnth (make_fixnum (5), Ffile_attributes (filename, Qnil)); + if (suffix_p (filename, ".gz")) filename = Fsubstring (filename, Qnil, make_fixnum (-3)); filename = Fexpand_file_name (filename, Qnil); /* We create eln filenames with an hash in order to look-up these starting from the source filename, IOW have a relation - /absolute/path/filename.el -> eln-cache/filename-hash.eln. + + /absolute/path/filename.el + last_mod_time -> + eln-cache/filename-hash.eln. + + 'dlopen' can return the same handle if two shared with the same + filename are loaded in two different times (even if the first was + deleted!). To prevent this scenario the last modification time + of the source file is included in the hashing algorithm. As installing .eln files compiled during the build changes their absolute path we need an hashing mechanism that is not sensitive @@ -3910,7 +3923,9 @@ If BASE-DIR is nil use the first entry in `comp-eln-load-path'. */) } } - Lisp_Object hash = Fsubstring (comp_hash_string (filename), Qnil, + Lisp_Object hash_input = + concat2 (filename, Fprin1_to_string (last_mod_time, Qnil)); + Lisp_Object hash = Fsubstring (comp_hash_string (hash_input), Qnil, make_fixnum (ELN_FILENAME_HASH_LEN)); filename = concat2 (Ffile_name_nondirectory (Fsubstring (filename, Qnil, make_fixnum (-3))), diff --git a/src/lread.c b/src/lread.c index 521da4e1d81..6b585fcaccc 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1635,19 +1635,13 @@ maybe_swap_for_eln (Lisp_Object *filename, int *fd, struct timespec mtime) emacs_close (eln_fd); else { - struct timespec eln_mtime = get_stat_mtime (&eln_st); - if (timespec_cmp (eln_mtime, mtime) > 0) - { - *filename = eln_name; - emacs_close (*fd); - *fd = eln_fd; - /* Store the eln -> el relation. */ - Fputhash (Ffile_name_nondirectory (eln_name), - el_name, Vcomp_eln_to_el_h); - return; - } - else - emacs_close (eln_fd); + *filename = eln_name; + emacs_close (*fd); + *fd = eln_fd; + /* Store the eln -> el relation. */ + Fputhash (Ffile_name_nondirectory (eln_name), + el_name, Vcomp_eln_to_el_h); + return; } } } -- 2.39.5