[Bug 269207] localtime.c fails to detect mobile device timezone change
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 269207] localtime.c fails to detect mobile device timezone change"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 269207] localtime.c fails to detect mobile device timezone change"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 269207] localtime.c fails to detect mobile device timezone change"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 28 Jan 2023 17:38:24 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=269207 Bug ID: 269207 Summary: localtime.c fails to detect mobile device timezone change Product: Base System Version: CURRENT Hardware: Any OS: Any Status: New Severity: Affects Many People Priority: --- Component: bin Assignee: bugs@FreeBSD.org Reporter: fbsd@opal.com Currently, localtime(3) determines the local timezone using either the TZ environment variable or the /etc/localtime file. Once it has obtained the zone information, a flag is set, the zone information is cached and the information is re-used on subsequent calls to localtime() by the same program. In situations where long-running programs persist over mobile device moves that span timezones, this behavior means that such programs will remain unaware of any system timezone changes, resulting in events occurring at times not expected by the user. A real-world example is a laptop that executes cron(8) jobs at local times. The user suspends the laptop, travels to a new timezone, resumes the laptop and updates the system timezone information using tzsetup(8) or other means. Currently, cron(8) continues to execute jobs at times of the original timezone. Desired behavior is that cron(8) starts to use the new timezone. Similarly for other long-running programs. Of course, long-running programs can be restarted after the timezone move. However, this may be undesirable, and restarting system programs such as cron(8) is not something that non-technical users may be aware of the need for or even have sufficient privileges to do. In localtime.c, the flag (the variable "lcl_is_set") is used both by tzset_basic() and tzsetwall_basic(). In tzset_basic(), the flag is set to the length of the zoneinfo provided in the TZ environment variable which, of course, will not change for the life of a long-running program. In tzsetwall_basic(), the flag is set to -1 when the zone information is read from /etc/localtime. As described above, this file could be changed during the life of a long-running program. The use of the lcl_is_set flag is therefore not suitable in this case. The attached patch removes the use of lcl_is_set from tzsetwall_basic() and replaces it with examination of the zone file's mtime in tzload() instead. Once the zone information has been loaded from the file, the file's name and mtime are stored. On subsequent calls, if these are unchanged, the cached zone information is returned. Otherwise the file is re-read to obtain the new zone information. When the TZ environment variable is unset, the existing code has the following calling sequence: localtime() => tzset_basic() => tzsetwall_basic() => tzload() => tzparse() => tzload() The first call to tzload() is to load the /etc/localtime zone file. The second call to tzload() is to load the TZDEFRULES ("posixrules") zone file. The proposed patch is therefore aware of this and ignores that file when saving the zone file's name and mtime. The patch also reorders tzload()'s _open() and _fstat() sequence to be a stat() followed by _open() in order to avoid unnecessarily opening an unchanged file and therefore triggering an unnecessary update of the inode's atime. Long-running programs started with a timezone specification in the TZ environment variable are unaffected by this patch. Even if /etc/localtime is modified for a new timezone, such programs will continue to use the timezone specification in their TZ variable. This patch only affects programs for which the TZ environment variable is not set and so /etc/localtime is used, or programs calling tzsetwall(3) directly. Also attached are a simple test program that calls localtime() repeatedly every 5 seconds and a Makefile to compile it and a patched localtime.c in a test directory. Run the program and then use tzsetup() or otherwise modify /etc/localtime to a different timezone while the program is running. -- You are receiving this mail because: You are the assignee for the bug.