diff options
| author | Andrea Corallo | 2020-08-19 15:26:42 +0200 |
|---|---|---|
| committer | Andrea Corallo | 2020-08-19 16:29:56 +0200 |
| commit | 8a931a97b8dd19a38d6f719f810280a07ba76438 (patch) | |
| tree | b10244eb096cf0a70bce0385b6d657b98542500b | |
| parent | 886377fefd03a7b893afad28746e69615a300994 (diff) | |
| download | emacs-8a931a97b8dd19a38d6f719f810280a07ba76438.tar.gz emacs-8a931a97b8dd19a38d6f719f810280a07ba76438.zip | |
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.
| -rw-r--r-- | src/comp.c | 19 | ||||
| -rw-r--r-- | 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'. */) | |||
| 3872 | { | 3872 | { |
| 3873 | CHECK_STRING (filename); | 3873 | CHECK_STRING (filename); |
| 3874 | 3874 | ||
| 3875 | if (NILP (Ffile_exists_p (filename))) | ||
| 3876 | xsignal1 (Qfile_missing, filename); | ||
| 3877 | |||
| 3878 | Lisp_Object last_mod_time = | ||
| 3879 | Fnth (make_fixnum (5), Ffile_attributes (filename, Qnil)); | ||
| 3880 | |||
| 3875 | if (suffix_p (filename, ".gz")) | 3881 | if (suffix_p (filename, ".gz")) |
| 3876 | filename = Fsubstring (filename, Qnil, make_fixnum (-3)); | 3882 | filename = Fsubstring (filename, Qnil, make_fixnum (-3)); |
| 3877 | filename = Fexpand_file_name (filename, Qnil); | 3883 | filename = Fexpand_file_name (filename, Qnil); |
| 3878 | 3884 | ||
| 3879 | /* We create eln filenames with an hash in order to look-up these | 3885 | /* We create eln filenames with an hash in order to look-up these |
| 3880 | starting from the source filename, IOW have a relation | 3886 | starting from the source filename, IOW have a relation |
| 3881 | /absolute/path/filename.el -> eln-cache/filename-hash.eln. | 3887 | |
| 3888 | /absolute/path/filename.el + last_mod_time -> | ||
| 3889 | eln-cache/filename-hash.eln. | ||
| 3890 | |||
| 3891 | 'dlopen' can return the same handle if two shared with the same | ||
| 3892 | filename are loaded in two different times (even if the first was | ||
| 3893 | deleted!). To prevent this scenario the last modification time | ||
| 3894 | of the source file is included in the hashing algorithm. | ||
| 3882 | 3895 | ||
| 3883 | As installing .eln files compiled during the build changes their | 3896 | As installing .eln files compiled during the build changes their |
| 3884 | absolute path we need an hashing mechanism that is not sensitive | 3897 | 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'. */) | |||
| 3910 | } | 3923 | } |
| 3911 | } | 3924 | } |
| 3912 | 3925 | ||
| 3913 | Lisp_Object hash = Fsubstring (comp_hash_string (filename), Qnil, | 3926 | Lisp_Object hash_input = |
| 3927 | concat2 (filename, Fprin1_to_string (last_mod_time, Qnil)); | ||
| 3928 | Lisp_Object hash = Fsubstring (comp_hash_string (hash_input), Qnil, | ||
| 3914 | make_fixnum (ELN_FILENAME_HASH_LEN)); | 3929 | make_fixnum (ELN_FILENAME_HASH_LEN)); |
| 3915 | filename = concat2 (Ffile_name_nondirectory (Fsubstring (filename, Qnil, | 3930 | filename = concat2 (Ffile_name_nondirectory (Fsubstring (filename, Qnil, |
| 3916 | make_fixnum (-3))), | 3931 | 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) | |||
| 1635 | emacs_close (eln_fd); | 1635 | emacs_close (eln_fd); |
| 1636 | else | 1636 | else |
| 1637 | { | 1637 | { |
| 1638 | struct timespec eln_mtime = get_stat_mtime (&eln_st); | 1638 | *filename = eln_name; |
| 1639 | if (timespec_cmp (eln_mtime, mtime) > 0) | 1639 | emacs_close (*fd); |
| 1640 | { | 1640 | *fd = eln_fd; |
| 1641 | *filename = eln_name; | 1641 | /* Store the eln -> el relation. */ |
| 1642 | emacs_close (*fd); | 1642 | Fputhash (Ffile_name_nondirectory (eln_name), |
| 1643 | *fd = eln_fd; | 1643 | el_name, Vcomp_eln_to_el_h); |
| 1644 | /* Store the eln -> el relation. */ | 1644 | return; |
| 1645 | Fputhash (Ffile_name_nondirectory (eln_name), | ||
| 1646 | el_name, Vcomp_eln_to_el_h); | ||
| 1647 | return; | ||
| 1648 | } | ||
| 1649 | else | ||
| 1650 | emacs_close (eln_fd); | ||
| 1651 | } | 1645 | } |
| 1652 | } | 1646 | } |
| 1653 | } | 1647 | } |