diff options
| author | Paul Eggert | 2024-08-15 12:58:19 -0700 |
|---|---|---|
| committer | Paul Eggert | 2024-08-15 13:31:31 -0700 |
| commit | 4b6b9a7acdc4f7d0594caaaa382e2e633f8f1225 (patch) | |
| tree | 6b522f0bca6835c62d10692b89be22638d27f185 /src | |
| parent | cbacdca9e3f6dcf9b88704391f06daf7301608b0 (diff) | |
| download | emacs-4b6b9a7acdc4f7d0594caaaa382e2e633f8f1225.tar.gz emacs-4b6b9a7acdc4f7d0594caaaa382e2e633f8f1225.zip | |
Avoid some GC when locking/unlocking files
* src/filelock.c (lock_file_1, current_lock_owner):
Don’t possibly invoke the garbage collector when
comparing lock file contents to host names.
Diffstat (limited to 'src')
| -rw-r--r-- | src/filelock.c | 62 |
1 files changed, 37 insertions, 25 deletions
diff --git a/src/filelock.c b/src/filelock.c index 55ab15feb8d..cdf9e6f0ffc 100644 --- a/src/filelock.c +++ b/src/filelock.c | |||
| @@ -271,27 +271,29 @@ lock_file_1 (Lisp_Object lfname, bool force) | |||
| 271 | intmax_t boot = get_boot_sec (); | 271 | intmax_t boot = get_boot_sec (); |
| 272 | Lisp_Object luser_name = Fuser_login_name (Qnil); | 272 | Lisp_Object luser_name = Fuser_login_name (Qnil); |
| 273 | Lisp_Object lhost_name = Fsystem_name (); | 273 | Lisp_Object lhost_name = Fsystem_name (); |
| 274 | |||
| 275 | /* Protect against the extremely unlikely case of the host name | ||
| 276 | containing an @ character. */ | ||
| 277 | if (!NILP (lhost_name) && strchr (SSDATA (lhost_name), '@')) | ||
| 278 | lhost_name = CALLN (Ffuncall, Qstring_replace, | ||
| 279 | build_string ("@"), build_string ("-"), | ||
| 280 | lhost_name); | ||
| 281 | |||
| 282 | char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : ""; | 274 | char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : ""; |
| 283 | char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : ""; | 275 | char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : ""; |
| 284 | char lock_info_str[MAX_LFINFO + 1]; | 276 | char lock_info_str[MAX_LFINFO + 1]; |
| 285 | intmax_t pid = getpid (); | 277 | intmax_t pid = getpid (); |
| 286 | 278 | ||
| 287 | char const *lock_info_fmt = (boot | 279 | int room = sizeof lock_info_str; |
| 288 | ? "%s@%s.%"PRIdMAX":%"PRIdMAX | 280 | int len = snprintf (lock_info_str, room, "%s@", user_name); |
| 289 | : "%s@%s.%"PRIdMAX); | ||
| 290 | int len = snprintf (lock_info_str, sizeof lock_info_str, | ||
| 291 | lock_info_fmt, user_name, host_name, pid, boot); | ||
| 292 | if (! (0 <= len && len < sizeof lock_info_str)) | 281 | if (! (0 <= len && len < sizeof lock_info_str)) |
| 293 | return ENAMETOOLONG; | 282 | return ENAMETOOLONG; |
| 294 | 283 | /* Protect against the extremely unlikely case of the host name | |
| 284 | containing an @ character. */ | ||
| 285 | for (; *host_name; len++, host_name++) | ||
| 286 | { | ||
| 287 | if (! (len < sizeof lock_info_str - 1)) | ||
| 288 | return ENAMETOOLONG; | ||
| 289 | lock_info_str[len] = *host_name == '@' ? '-' : *host_name; | ||
| 290 | } | ||
| 291 | char const *lock_info_fmt = boot ? ".%"PRIdMAX":%"PRIdMAX : ".%"PRIdMAX; | ||
| 292 | room = sizeof lock_info_str - len; | ||
| 293 | int suffixlen = snprintf (lock_info_str + len, room, | ||
| 294 | lock_info_fmt, pid, boot); | ||
| 295 | if (! (0 <= suffixlen && suffixlen < room)) | ||
| 296 | return ENAMETOOLONG; | ||
| 295 | return create_lock_file (SSDATA (lfname), lock_info_str, force); | 297 | return create_lock_file (SSDATA (lfname), lock_info_str, force); |
| 296 | } | 298 | } |
| 297 | 299 | ||
| @@ -448,22 +450,32 @@ current_lock_owner (lock_info_type *owner, Lisp_Object lfname) | |||
| 448 | if (lfinfo_end != owner->user + lfinfolen) | 450 | if (lfinfo_end != owner->user + lfinfolen) |
| 449 | return EINVAL; | 451 | return EINVAL; |
| 450 | 452 | ||
| 453 | char *linkhost = at + 1; | ||
| 454 | ptrdiff_t linkhostlen = dot - linkhost; | ||
| 451 | Lisp_Object system_name = Fsystem_name (); | 455 | Lisp_Object system_name = Fsystem_name (); |
| 452 | /* If `system-name' returns nil, that means we're in a | 456 | /* If `system-name' returns nil, that means we're in a |
| 453 | --no-build-details Emacs, and the name part of the link (e.g., | 457 | --no-build-details Emacs, and the name part of the link (e.g., |
| 454 | .#test.txt -> larsi@.118961:1646577954) is an empty string. */ | 458 | .#test.txt -> larsi@.118961:1646577954) is an empty string. */ |
| 459 | bool on_current_host; | ||
| 455 | if (NILP (system_name)) | 460 | if (NILP (system_name)) |
| 456 | system_name = build_string (""); | 461 | on_current_host = linkhostlen == 0; |
| 457 | /* Protect against the extremely unlikely case of the host name | 462 | else |
| 458 | containing an @ character. */ | 463 | { |
| 459 | else if (strchr (SSDATA (system_name), '@')) | 464 | on_current_host = linkhostlen == SBYTES (system_name); |
| 460 | system_name = CALLN (Ffuncall, intern ("string-replace"), | 465 | if (on_current_host) |
| 461 | build_string ("@"), build_string ("-"), | 466 | { |
| 462 | system_name); | 467 | /* Protect against the extremely unlikely case of the host |
| 463 | /* On current host? */ | 468 | name containing '@'. */ |
| 464 | if (STRINGP (system_name) | 469 | char *sysname = SSDATA (system_name); |
| 465 | && dot - (at + 1) == SBYTES (system_name) | 470 | for (ptrdiff_t i = 0; i < linkhostlen; i++) |
| 466 | && memcmp (at + 1, SSDATA (system_name), SBYTES (system_name)) == 0) | 471 | if (linkhost[i] != (sysname[i] == '@' ? '-' : sysname[i])) |
| 472 | { | ||
| 473 | on_current_host = false; | ||
| 474 | break; | ||
| 475 | } | ||
| 476 | } | ||
| 477 | } | ||
| 478 | if (on_current_host) | ||
| 467 | { | 479 | { |
| 468 | if (pid == getpid ()) | 480 | if (pid == getpid ()) |
| 469 | return I_OWN_IT; | 481 | return I_OWN_IT; |