diff options
| author | Paul Eggert | 2023-08-12 19:39:11 -0700 |
|---|---|---|
| committer | Paul Eggert | 2023-08-12 19:46:12 -0700 |
| commit | 5e736ca6ccfa131736ab0b3a298de2cb319e7dfb (patch) | |
| tree | 65b06f7a73dc2a04c60af430bc95102a347979df /src | |
| parent | b35431b218ada2d84eb251d18e5543388b598d80 (diff) | |
| download | emacs-5e736ca6ccfa131736ab0b3a298de2cb319e7dfb.tar.gz emacs-5e736ca6ccfa131736ab0b3a298de2cb319e7dfb.zip | |
Improve boot-time gathering
Simplify Emacs proper by using Gnulib’s boot-time module
instead of doing it all by hand. This should port Emacs
better to obscurish hosts, as Bruno Haible has merged the
best of Emacs’s and Gnulib’s boot-time gathering.
* lib/boot-time-aux.h, lib/boot-time.c, lib/boot-time.h:
* lib/readutmp.h, m4/readutmp.m4: New files, copied from Gnulib.
* admin/merge-gnulib (GNULIB_MODULES): Add boot-time.
* configure.ac: Do not check for utmp.h;
the boot-time module now does this.
(BOOT_TIME_FILE): Remove; no longer used.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* src/filelock.c [__FreeBSD__]: Do not include <sys/sysctl.h>.
[HAVE_UTMP_H]: Do not include utmp.h.
Include boot-time instead: boot-time does the work now.
(BOOT_TIME) [HAVE_ANDROID && !ANDROID_STUBIFY]: Don’t undef.
(WTMP_FILE): Don’t define.
(boot_time, boot_time_initialized, get_boot_time_1, get_boot_time):
Remove.
(get_boot_sec): New function that simply calls Gnulib get_boot_time.
(lock_file_1, current_lock_owner): Use get_boot_sec instead
of get_boot_time.
Diffstat (limited to 'src')
| -rw-r--r-- | src/filelock.c | 172 |
1 files changed, 10 insertions, 162 deletions
diff --git a/src/filelock.c b/src/filelock.c index 3b1ff8ad566..d2161f1e58a 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -36,13 +36,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 36 | #include <sys/file.h> | 36 | #include <sys/file.h> |
| 37 | #include <fcntl.h> | 37 | #include <fcntl.h> |
| 38 | #include <unistd.h> | 38 | #include <unistd.h> |
| 39 | |||
| 40 | #ifdef __FreeBSD__ | ||
| 41 | #include <sys/sysctl.h> | ||
| 42 | #endif /* __FreeBSD__ */ | ||
| 43 | |||
| 44 | #include <errno.h> | 39 | #include <errno.h> |
| 45 | 40 | ||
| 41 | #include <boot-time.h> | ||
| 46 | #include <c-ctype.h> | 42 | #include <c-ctype.h> |
| 47 | 43 | ||
| 48 | #include "lisp.h" | 44 | #include "lisp.h" |
| @@ -55,20 +51,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 55 | 51 | ||
| 56 | #ifndef MSDOS | 52 | #ifndef MSDOS |
| 57 | 53 | ||
| 58 | #ifdef HAVE_UTMP_H | ||
| 59 | #include <utmp.h> | ||
| 60 | #endif | ||
| 61 | |||
| 62 | /* Boot time is not available on Android. */ | ||
| 63 | |||
| 64 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 65 | #undef BOOT_TIME | ||
| 66 | #endif | ||
| 67 | |||
| 68 | #if !defined WTMP_FILE && !defined WINDOWSNT && defined BOOT_TIME | ||
| 69 | #define WTMP_FILE "/var/log/wtmp" | ||
| 70 | #endif | ||
| 71 | |||
| 72 | #ifdef HAVE_ANDROID | 54 | #ifdef HAVE_ANDROID |
| 73 | #include "android.h" /* For `android_is_special_directory'. */ | 55 | #include "android.h" /* For `android_is_special_directory'. */ |
| 74 | #endif /* HAVE_ANDROID */ | 56 | #endif /* HAVE_ANDROID */ |
| @@ -127,153 +109,19 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 127 | 109 | ||
| 128 | /* Return the time of the last system boot. */ | 110 | /* Return the time of the last system boot. */ |
| 129 | 111 | ||
| 130 | static time_t boot_time; | ||
| 131 | static bool boot_time_initialized; | ||
| 132 | |||
| 133 | #ifdef BOOT_TIME | ||
| 134 | static void get_boot_time_1 (const char *, bool); | ||
| 135 | #endif | ||
| 136 | |||
| 137 | static time_t | 112 | static time_t |
| 138 | get_boot_time (void) | 113 | get_boot_sec (void) |
| 139 | { | 114 | { |
| 140 | if (boot_time_initialized) | 115 | /* get_boot_time maintains static state. Don't touch that state |
| 141 | return boot_time; | ||
| 142 | boot_time_initialized = 1; | ||
| 143 | |||
| 144 | #if defined (CTL_KERN) && defined (KERN_BOOTTIME) | ||
| 145 | { | ||
| 146 | int mib[2]; | ||
| 147 | size_t size; | ||
| 148 | struct timeval boottime_val; | ||
| 149 | |||
| 150 | mib[0] = CTL_KERN; | ||
| 151 | mib[1] = KERN_BOOTTIME; | ||
| 152 | size = sizeof (boottime_val); | ||
| 153 | |||
| 154 | if (sysctl (mib, 2, &boottime_val, &size, NULL, 0) >= 0 && size != 0) | ||
| 155 | { | ||
| 156 | boot_time = boottime_val.tv_sec; | ||
| 157 | return boot_time; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | #endif /* defined (CTL_KERN) && defined (KERN_BOOTTIME) */ | ||
| 161 | |||
| 162 | #ifdef BOOT_TIME_FILE | ||
| 163 | { | ||
| 164 | struct stat st; | ||
| 165 | if (stat (BOOT_TIME_FILE, &st) == 0) | ||
| 166 | { | ||
| 167 | boot_time = st.st_mtime; | ||
| 168 | return boot_time; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | #endif /* BOOT_TIME_FILE */ | ||
| 172 | |||
| 173 | #if defined (BOOT_TIME) | ||
| 174 | /* The utmp routines maintain static state. Don't touch that state | ||
| 175 | if we are going to dump, since it might not survive dumping. */ | 116 | if we are going to dump, since it might not survive dumping. */ |
| 176 | if (will_dump_p ()) | 117 | if (will_dump_p ()) |
| 177 | return boot_time; | 118 | return 0; |
| 178 | |||
| 179 | /* Try to get boot time from utmp before wtmp, | ||
| 180 | since utmp is typically much smaller than wtmp. | ||
| 181 | Passing a null pointer causes get_boot_time_1 | ||
| 182 | to inspect the default file, namely utmp. */ | ||
| 183 | get_boot_time_1 (0, 0); | ||
| 184 | if (boot_time) | ||
| 185 | return boot_time; | ||
| 186 | |||
| 187 | /* Try to get boot time from the current wtmp file. */ | ||
| 188 | get_boot_time_1 (WTMP_FILE, 1); | ||
| 189 | |||
| 190 | /* If we did not find a boot time in wtmp, look at wtmp.1, | ||
| 191 | wtmp.1.gz, wtmp.2, wtmp.2.gz, and so on. */ | ||
| 192 | for (int counter = 0; counter < 20 && ! boot_time; counter++) | ||
| 193 | { | ||
| 194 | Lisp_Object filename = Qnil; | ||
| 195 | bool delete_flag = false; | ||
| 196 | char cmd_string[sizeof WTMP_FILE ".19.gz"]; | ||
| 197 | AUTO_STRING_WITH_LEN (tempname, cmd_string, | ||
| 198 | sprintf (cmd_string, "%s.%d", WTMP_FILE, counter)); | ||
| 199 | if (! NILP (Ffile_exists_p (tempname))) | ||
| 200 | filename = tempname; | ||
| 201 | else | ||
| 202 | { | ||
| 203 | tempname = make_formatted_string (cmd_string, "%s.%d.gz", | ||
| 204 | WTMP_FILE, counter); | ||
| 205 | if (! NILP (Ffile_exists_p (tempname))) | ||
| 206 | { | ||
| 207 | /* The utmp functions on older systems accept only file | ||
| 208 | names up to 8 bytes long. Choose a 2 byte prefix, so | ||
| 209 | the 6-byte suffix does not make the name too long. */ | ||
| 210 | filename = Fmake_temp_file_internal (build_string ("wt"), Qnil, | ||
| 211 | empty_unibyte_string, Qnil); | ||
| 212 | CALLN (Fcall_process, build_string ("gzip"), Qnil, | ||
| 213 | list2 (QCfile, filename), Qnil, | ||
| 214 | build_string ("-cd"), tempname); | ||
| 215 | delete_flag = true; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | if (! NILP (filename)) | ||
| 220 | { | ||
| 221 | get_boot_time_1 (SSDATA (filename), 1); | ||
| 222 | if (delete_flag) | ||
| 223 | emacs_unlink (SSDATA (filename)); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | return boot_time; | ||
| 228 | #else | ||
| 229 | return 0; | ||
| 230 | #endif | ||
| 231 | } | ||
| 232 | 119 | ||
| 233 | #ifdef BOOT_TIME | 120 | struct timespec boot_time; |
| 234 | /* Try to get the boot time from wtmp file FILENAME. | 121 | boot_time.tv_sec = 0; |
| 235 | This succeeds if that file contains a reboot record. | 122 | get_boot_time (&boot_time); |
| 236 | 123 | return boot_time.tv_sec; | |
| 237 | If FILENAME is zero, use the same file as before; | ||
| 238 | if no FILENAME has ever been specified, this is the utmp file. | ||
| 239 | Use the newest reboot record if NEWEST, | ||
| 240 | the first reboot record otherwise. | ||
| 241 | Ignore all reboot records on or before BOOT_TIME. | ||
| 242 | Success is indicated by setting BOOT_TIME to a larger value. */ | ||
| 243 | |||
| 244 | void | ||
| 245 | get_boot_time_1 (const char *filename, bool newest) | ||
| 246 | { | ||
| 247 | struct utmp ut, *utp; | ||
| 248 | |||
| 249 | if (filename) | ||
| 250 | utmpname (filename); | ||
| 251 | |||
| 252 | setutent (); | ||
| 253 | |||
| 254 | while (1) | ||
| 255 | { | ||
| 256 | /* Find the next reboot record. */ | ||
| 257 | ut.ut_type = BOOT_TIME; | ||
| 258 | utp = getutid (&ut); | ||
| 259 | if (! utp) | ||
| 260 | break; | ||
| 261 | /* Compare reboot times and use the newest one. */ | ||
| 262 | if (utp->ut_time > boot_time) | ||
| 263 | { | ||
| 264 | boot_time = utp->ut_time; | ||
| 265 | if (! newest) | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | /* Advance on element in the file | ||
| 269 | so that getutid won't repeat the same one. */ | ||
| 270 | utp = getutent (); | ||
| 271 | if (! utp) | ||
| 272 | break; | ||
| 273 | } | ||
| 274 | endutent (); | ||
| 275 | } | 124 | } |
| 276 | #endif /* BOOT_TIME */ | ||
| 277 | 125 | ||
| 278 | /* An arbitrary limit on lock contents length. 8 K should be plenty | 126 | /* An arbitrary limit on lock contents length. 8 K should be plenty |
| 279 | big enough in practice. */ | 127 | big enough in practice. */ |
| @@ -418,7 +266,7 @@ create_lock_file (char *lfname, char *lock_info_str, bool force) | |||
| 418 | static int | 266 | static int |
| 419 | lock_file_1 (Lisp_Object lfname, bool force) | 267 | lock_file_1 (Lisp_Object lfname, bool force) |
| 420 | { | 268 | { |
| 421 | intmax_t boot = get_boot_time (); | 269 | intmax_t boot = get_boot_sec (); |
| 422 | Lisp_Object luser_name = Fuser_login_name (Qnil); | 270 | Lisp_Object luser_name = Fuser_login_name (Qnil); |
| 423 | Lisp_Object lhost_name = Fsystem_name (); | 271 | Lisp_Object lhost_name = Fsystem_name (); |
| 424 | 272 | ||
| @@ -604,7 +452,7 @@ current_lock_owner (lock_info_type *owner, Lisp_Object lfname) | |||
| 604 | && (kill (pid, 0) >= 0 || errno == EPERM) | 452 | && (kill (pid, 0) >= 0 || errno == EPERM) |
| 605 | && (boot_time == 0 | 453 | && (boot_time == 0 |
| 606 | || (boot_time <= TYPE_MAXIMUM (time_t) | 454 | || (boot_time <= TYPE_MAXIMUM (time_t) |
| 607 | && within_one_second (boot_time, get_boot_time ())))) | 455 | && within_one_second (boot_time, get_boot_sec ())))) |
| 608 | return ANOTHER_OWNS_IT; | 456 | return ANOTHER_OWNS_IT; |
| 609 | /* The owner process is dead or has a strange pid, so try to | 457 | /* The owner process is dead or has a strange pid, so try to |
| 610 | zap the lockfile. */ | 458 | zap the lockfile. */ |