git: ddedf2a11eb2 - main - tzcode: Implement timezone change detection
Cy Schubert
Cy.Schubert at cschubert.com
Tue Sep 14 15:36:21 UTC 2021
In message <202109131442.18DEgDIn043709 at gitrepo.freebsd.org>, Edward Tomasz
Nap
ierala writes:
> The branch main has been updated by trasz:
>
> URL: https://cgit.FreeBSD.org/src/commit/?id=ddedf2a11eb20af1ee52cb3da70a57c2
> 1904af8f
>
> commit ddedf2a11eb20af1ee52cb3da70a57c21904af8f
> Author: Edward Tomasz Napierala <trasz at FreeBSD.org>
> AuthorDate: 2021-09-12 03:07:26 +0000
> Commit: Edward Tomasz Napierala <trasz at FreeBSD.org>
> CommitDate: 2021-09-12 03:07:58 +0000
>
> tzcode: Implement timezone change detection
>
> Implement optional timezone change detection for local time libc
> functions. This is disabled by default; set WITH_DETECT_TZ_CHANGES
> to build it.
>
> Reviewed By: imp
> Sponsored by: NetApp, Inc.
> Sponsored by: Klara, Inc.
> X-NetApp-PR: #47
> Differential Revision: https://reviews.freebsd.org/D30183
> ---
> contrib/tzcode/stdtime/localtime.c | 89 ++++++++++++++++++++++++++++
> +-
> lib/libc/stdtime/Makefile.inc | 4 ++
> share/mk/src.opts.mk | 1 +
> tools/build/options/WITH_DETECT_TZ_CHANGES | 2 +
> 4 files changed, 95 insertions(+), 1 deletion(-)
>
> diff --git a/contrib/tzcode/stdtime/localtime.c b/contrib/tzcode/stdtime/loca
> ltime.c
> index e221c1fa3964..926b24470e19 100644
> --- a/contrib/tzcode/stdtime/localtime.c
> +++ b/contrib/tzcode/stdtime/localtime.c
> @@ -354,6 +354,45 @@ settzname(void)
> }
> }
>
> +#ifdef DETECT_TZ_CHANGES
> +/*
> + * Determine if there's a change in the timezone since the last time we chec
> ked.
> + * Returns: -1 on error
> + * 0 if the timezone has not changed
> + * 1 if the timezone has changed
> + */
> +static int
> +change_in_tz(const char *name)
> +{
> + static char old_name[PATH_MAX];
> + static struct stat old_sb;
> + struct stat sb;
> + int error;
> +
> + error = stat(name, &sb);
> + if (error != 0)
> + return -1;
> +
> + if (strcmp(name, old_name) != 0) {
> + strlcpy(old_name, name, sizeof(old_name));
> + old_sb = sb;
> + return 1;
> + }
> +
> + if (sb.st_dev != old_sb.st_dev ||
> + sb.st_ino != old_sb.st_ino ||
> + sb.st_ctime != old_sb.st_ctime ||
> + sb.st_mtime != old_sb.st_mtime) {
> + old_sb = sb;
> + return 1;
> + }
> +
> + return 0;
> +}
> +#else /* !DETECT_TZ_CHANGES */
> +#define change_in_tz(X) 0
> +#endif /* !DETECT_TZ_CHANGES */
> +
> static int
> differ_by_repeat(const time_t t1, const time_t t0)
> {
> @@ -379,6 +418,7 @@ register const int doextend;
> int stored;
> int nread;
> int res;
> + int ret;
> union {
> struct tzhead tzhead;
> char buf[2 * sizeof(struct tzhead) +
> @@ -427,6 +467,22 @@ register const int doextend;
> (void) strcat(fullname, name);
> name = fullname;
> }
> + if (doextend == TRUE) {
> + /*
> + * Detect if the timezone file has changed. Check
> + * 'doextend' to ignore TZDEFRULES; the change_in_tz()
> + * function can only keep state for a single file.
> + */
> + ret = change_in_tz(name);
> + if (ret <= 0) {
> + /*
> + * Returns -1 if there was an error,
> + * and 0 if the timezone had not changed.
> + */
> + free(fullname);
> + return ret;
> + }
> + }
> if ((fid = _open(name, OPEN_MODE)) == -1) {
> free(fullname);
> return -1;
> @@ -1209,12 +1265,43 @@ gmtload(struct state *const sp)
> (void) tzparse(gmt, sp, TRUE);
> }
>
> +#ifdef DETECT_TZ_CHANGES
> +static int
> +recheck_tzdata()
> +{
> + static time_t last_checked;
> + struct timespec now;
> + time_t current_time;
> + int error;
> +
> + /*
> + * We want to recheck the timezone file every 61 sec.
> + */
> + error = clock_gettime(CLOCK_MONOTONIC, &now);
> + if (error <= 0) {
> + /* XXX: Can we somehow report this? */
> + return 0;
> + }
> +
> + current_time = now.tv_sec;
> + if ((current_time - last_checked > 61) ||
> + (last_checked > current_time)) {
> + last_checked = current_time;
> + return 1;
> + }
> +
> + return 0;
> +}
> +#else /* !DETECT_TZ_CHANGES */
> +#define recheck_tzdata() 0
> +#endif /* !DETECT_TZ_CHANGES */
> +
> static void
> tzsetwall_basic(int rdlocked)
> {
> if (!rdlocked)
> _RWLOCK_RDLOCK(&lcl_rwlock);
> - if (lcl_is_set < 0) {
> + if (lcl_is_set < 0 && recheck_tzdata() == 0) {
> if (!rdlocked)
> _RWLOCK_UNLOCK(&lcl_rwlock);
> return;
> diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
> index fb0d2b934148..3d483469bc97 100644
> --- a/lib/libc/stdtime/Makefile.inc
> +++ b/lib/libc/stdtime/Makefile.inc
> @@ -12,6 +12,10 @@ CFLAGS+= -I${SRCTOP}/contrib/tzcode/stdtime -I${LIBC_SRCTO
> P}/stdtime
>
> CFLAGS.localtime.c= -fwrapv
>
> +.if ${MK_DETECT_TZ_CHANGES} != "no"
> +CFLAGS+= -DDETECT_TZ_CHANGES
> +.endif
> +
> MAN+= ctime.3 strftime.3 strptime.3 time2posix.3
> MAN+= tzfile.5
>
> diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
> index 28e18260affd..ff894d3b3517 100644
> --- a/share/mk/src.opts.mk
> +++ b/share/mk/src.opts.mk
> @@ -196,6 +196,7 @@ __DEFAULT_NO_OPTIONS = \
> BHYVE_SNAPSHOT \
> CLANG_EXTRAS \
> CLANG_FORMAT \
> + DETECT_TZ_CHANGES \
> DTRACE_TESTS \
> EXPERIMENTAL \
> HESIOD \
> diff --git a/tools/build/options/WITH_DETECT_TZ_CHANGES b/tools/build/options
> /WITH_DETECT_TZ_CHANGES
> new file mode 100644
> index 000000000000..6a2d18473892
> --- /dev/null
> +++ b/tools/build/options/WITH_DETECT_TZ_CHANGES
> @@ -0,0 +1,2 @@
> +.\" $FreeBSD$
> +Make the time handling code detect changes to the timezone files.
>
Hi,
This patch caused all of the machines on my network to display UTC. After
reboot everything was ok. However moments ago my screen locked while typing
on my laptop. The time is now UTC instead of PDT. TZ is still set to
America/Vancouver. Changing the TZ makes no difference.
--
Cheers,
Cy Schubert <Cy.Schubert at cschubert.com>
FreeBSD UNIX: <cy at FreeBSD.org> Web: https://FreeBSD.org
NTP: <cy at nwtime.org> Web: https://nwtime.org
The need of the many outweighs the greed of the few.
More information about the dev-commits-src-main
mailing list