Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Jan 2023 17:38:24 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 269207] localtime.c fails to detect mobile device timezone change
Message-ID:  <bug-269207-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D269207

            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 informat=
ion
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.=
=20
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.=20
Currently, cron(8) continues to execute jobs at times of the original timez=
one.
 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.=
=20
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 re=
ad
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.=
=20
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 z=
one
information.

When the TZ environment variable is unset, the existing code has the follow=
ing
calling sequence:
    localtime() =3D> tzset_basic() =3D> tzsetwall_basic() =3D> tzload() =3D=
> tzparse()
=3D> tzload()
The first call to tzload() is to load the /etc/localtime zone file.  The se=
cond
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 st=
at()
followed by _open() in order to avoid unnecessarily opening an unchanged fi=
le
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 w=
hich
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 e=
very
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.

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-269207-227>