localtime and friends does not watch for timezone changes

Bug #11629 reported by Debian Bug Importer
32
Affects Status Importance Assigned to Milestone
glibc (Debian)
Fix Released
Unknown
glibc (Ubuntu)
Fix Released
Medium
Jeff Bailey
Revision history for this message
Debian Bug Importer (debzilla) wrote :

Message-ID: <email address hidden>
Date: Sun, 24 Oct 1999 04:59:16 -0700 (PDT)
From: "Sean 'Shaleh' Perry" <email address hidden>
To: <email address hidden>
Subject: localtime and friends does not watch for timezone changes

Package: libc6
Version: 2.1.2-5

applications using localtime to acquire locale or timezone data are not
informed of a timezone switch. So, if you start and application that uses
strftime() for instance, then run tzconfig to change the timezone, the proper
time is not shown, instead the previous value is.

one:~/test_code$ ./time
Sun Oct 24 7:56 AM EDT EST,EDT
Sun Oct 24 7:56 AM EDT EST,EDT
< run tzconfig on another term >
Sun Oct 24 7:56 AM EDT EST,EDT
Sun Oct 24 7:56 AM EDT EST,EDT
Sun Oct 24 7:57 AM EDT EST,EDT
Sun Oct 24 7:57 AM EDT EST,EDT
Sun Oct 24 7:57 AM EDT EST,EDT
Sun Oct 24 7:57 AM EDT EST,EDT
Sun Oct 24 7:57 AM EDT EST,EDT
Sun Oct 24 7:57 AM EDT EST,EDT
Sun Oct 24 7:57 AM EDT EST,EDT

note how time never changes

while (1) {
        tmp = time(NULL);
        tt = localtime(&tmp);
        strftime(t, 1024, "%a %b %e %l:%M %p %Z", tt);
        printf("%s %s,%s\n", t, tzname[0], tzname[1]);
        memset(t, '\0', 1024);
        sleep(1);
}

simple code I used to prove this exists.

If I can help, please contact me.

Revision history for this message
Debian Bug Importer (debzilla) wrote :

Message-ID: <email address hidden>
Date: Sun, 31 Oct 1999 11:46:28 -0700 (PST)
From: "Sean 'Shaleh' Perry" <email address hidden>
To: <email address hidden>
Cc: <email address hidden>
Subject: more info

Well, the move from daylight savings time happened last night. Oddly enough,
all of my running clock applications caught this change. So there obviously is
a setting in there somewhere to tell localtime() and friends to re-read the
info.

Revision history for this message
Debian Bug Importer (debzilla) wrote :

Message-ID: <email address hidden>
Date: Mon, 21 Oct 2002 19:26:07 -0700
From: Jeff Bailey <email address hidden>
To: <email address hidden>
Subject: Timezone bug

Sean,

Heya - I'm just cleaning house on some of the glibc bugs. Basically,
it looks like there's alot of machinery in there to handle daylight
savings time, leap seconds, etc. It appears that the actual timezone
and such are cached as an optimizations. Is this unacceptable for
some reason? Without a strong argument, it's unlikely that I'll get
upstream to consider changing this.

Tks,
Jeff Bailey

--
learning from failures is nice in theory...
but in practice, it sucks :)
 - Wolfgang Jaehrling

Revision history for this message
Debian Bug Importer (debzilla) wrote :
Download full text (3.6 KiB)

Message-Id: <1059384152.25976.32.camel@wilma>
Date: 28 Jul 2003 17:05:04 +0100
From: Ian Redfern <email address hidden>
To: <email address hidden>
Cc: <email address hidden>
Subject: Solution

I've also just hit this problem using a laptop while flying from
Amsterdam to London - and the two bugs are basically the same thing.

The problem is with the routine tzset_internal(int) in tzset.c in libc6.

It does the following:

  /* Examine the TZ environment variable. */
  tz = getenv ("TZ");
  if (tz == NULL)
    /* No user specification; use the site-wide default. */
    tz = TZDEFAULT;

[..]

  /* Check whether the value changes since the last run. */
  if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
    /* No change, simply return. */
    return;

Now, TZDEFAULT is /etc/localtime, which is a symlink on a Debian system.
Thus, when you call tzset() (or localtime(), which calls it) after
changing the system timezone with tzconfig, it has absolutely no effect
- it really should be looking at the name of the target of the symlink,
not the name of the symlink itself.

The result of this is that changing the timezone effectively requires
rebooting the machine to ensure all processes detect the change.

There is a way around it: if the code has something like the following
in its inner loop:

        if (!getenv("TZ"))
        {
            putenv("TZ=GMT");
            tzset();
            putenv("TZ");
        }

this will force the code to reevaluate the timezone file - twice. This
is however CPU-inefficient and would require all programs on the system
that deal with time (from syslog to Evolution) to jump through this
hoop.

A better solution would be the following patch to tzset.c which checks
/etc/localtime for modification each time it is called:

redferni@wilma:~$ diff -u tzset.c.orig tzset.c
--- tzset.c.orig 2002-03-12 09:19:36.000000000 +0000
+++ tzset.c 2003-07-24 16:57:33.000000000 +0100
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <time.h>

@@ -147,11 +148,13 @@
      int always;
 {
   static int is_initialized;
+ static time_t file_lastmod;
   register const char *tz;
   register size_t l;
   char *tzbuf;
   unsigned short int hh, mm, ss;
   unsigned short int whichrule;
+ struct stat sbuf;

   if (is_initialized && !always)
     return;
@@ -174,8 +177,15 @@

   /* Check whether the value changes since the last run. */
   if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
- /* No change, simply return. */
- return;
+ {
+ /* Check if symlink has new target */
+ if (!lstat(tz, &sbuf) && sbuf.st_mtime == file_lastmod)
+ {
+ /* No change, simply return. */
+ return;
+ }
+ file_lastmod = sbuf.st_mtime;
+ }

   tz_rules[0].name = NULL;
   tz_rules[1].name = NULL;

It adds a call to stat() to each call to localtime, but ensures that
every program on the system changes when the timezone changes - quite
invaluable to those of us who travel with laptops and irrelevant to
anyone else. It can be switched off by setting the TZ variable
explicitly.

If the GNOME clock people can put the inn...

Read more...

Revision history for this message
Debian Bug Importer (debzilla) wrote :

Message-ID: <email address hidden>
Date: Sun, 21 Mar 2004 22:32:07 -0600 (CST)
From: Bruce Allen <email address hidden>
To: <email address hidden>
cc: <email address hidden>, Guido Guenther <email address hidden>
Subject: slightly modified fix

Hi Ian,

I found your posting very helpful.

The bug still seems to be there at least under glibc 2.3.2 (redhat 9).
I noticed it in smartd (package: smartmontools) and have just fixed it in
the code.

One small item. I think your suggested inner loop block:
        if (!getenv("TZ"))
        {
            putenv("TZ=GMT");
            tzset();
            putenv("TZ");
        }

should read:
        if (!getenv("TZ"))
        {
            putenv("TZ=GMT");
            tzset();
            putenv("TZ");
            tzset();
         }
since you were flying to London, you might not have noticed this!

Cheers,
 Bruce

Revision history for this message
Debian Bug Importer (debzilla) wrote :

Message-ID: <email address hidden>
Date: Fri, 22 Oct 2004 11:40:28 +0900
From: GOTO Masanori <email address hidden>
To: Ian Redfern <email address hidden>, <email address hidden>,
 "Sean 'Shaleh' Perry" <email address hidden>, Jeff Bailey <email address hidden>,
 Bruce Allen <email address hidden>
Cc: <email address hidden>, <email address hidden>
Subject: Re: Bug#48184: Solution

At 28 Jul 2003 17:05:04 +0100,
Ian Redfern wrote:
> Now, TZDEFAULT is /etc/localtime, which is a symlink on a Debian system.
> Thus, when you call tzset() (or localtime(), which calls it) after
> changing the system timezone with tzconfig, it has absolutely no effect
> - it really should be looking at the name of the target of the symlink,
> not the name of the symlink itself.
>
> The result of this is that changing the timezone effectively requires
> rebooting the machine to ensure all processes detect the change.
>
> There is a way around it: if the code has something like the following
> in its inner loop:
>
> if (!getenv("TZ"))
> {
> putenv("TZ=GMT");
> tzset();
> putenv("TZ");
> }
>
> this will force the code to reevaluate the timezone file - twice. This
> is however CPU-inefficient and would require all programs on the system
> that deal with time (from syslog to Evolution) to jump through this
> hoop.

It can be used in the internal of applications.

> A better solution would be the following patch to tzset.c which checks
> /etc/localtime for modification each time it is called:

If we apply it, whenever we issue time related function, not only
time(2) but also lstat(2) is issued. Filesystem related operation is
slow (imagine floppy root fs!). Your request is very rare; most user
do not want such function performance drop.

> It adds a call to stat() to each call to localtime, but ensures that
> every program on the system changes when the timezone changes - quite
> invaluable to those of us who travel with laptops and irrelevant to
> anyone else. It can be switched off by setting the TZ variable
> explicitly.
>
> If the GNOME clock people can put the inner loop patch at the start of
> clock.c:update_clock(), this would fix the problem for GNOME clock, but
> I would prefer to see libc6 fix it globally.

Yes, application modification is the easiest way. And it make sense
when we imagine for example dynamic locale change. It needs
application modification.

If you want to support dynamic timezone switch eagerly, I think one
way to improve is adding new environment variable (ex: TZ_UPDATE). If
TZ_UPDATE is defined, then everytime tzset() checks timezone variable
through tzset() in each time. However one major drawback is user
needs to set TZ_UPDATE environment variable before he wants to use
dynamic timezone switch and before he invokes applications. So I
wonder it is really useful for most users.

Regards,
-- gotom

Revision history for this message
Debian Bug Importer (debzilla) wrote :
Download full text (3.2 KiB)

Message-ID: <email address hidden>
Date: Thu, 21 Oct 2004 23:20:43 -0500 (CDT)
From: Bruce Allen <email address hidden>
To: GOTO Masanori <email address hidden>
cc: Ian Redfern <email address hidden>, <email address hidden>,
 "Sean 'Shaleh' Perry" <email address hidden>, Jeff Bailey <email address hidden>, <email address hidden>
Subject: Re: Bug#48184: Solution

I filed a glibc bug report about this many months ago, and the maintainer
fixed it recently. Check glibc buzilla (I think that the home is at
redhat these days) to confirm.

Cheers,
 Bruce

On Fri, 22 Oct 2004, GOTO Masanori wrote:

> At 28 Jul 2003 17:05:04 +0100,
> Ian Redfern wrote:
> > Now, TZDEFAULT is /etc/localtime, which is a symlink on a Debian system.
> > Thus, when you call tzset() (or localtime(), which calls it) after
> > changing the system timezone with tzconfig, it has absolutely no effect
> > - it really should be looking at the name of the target of the symlink,
> > not the name of the symlink itself.
> >
> > The result of this is that changing the timezone effectively requires
> > rebooting the machine to ensure all processes detect the change.
> >
> > There is a way around it: if the code has something like the following
> > in its inner loop:
> >
> > if (!getenv("TZ"))
> > {
> > putenv("TZ=GMT");
> > tzset();
> > putenv("TZ");
> > }
> >
> > this will force the code to reevaluate the timezone file - twice. This
> > is however CPU-inefficient and would require all programs on the system
> > that deal with time (from syslog to Evolution) to jump through this
> > hoop.
>
> It can be used in the internal of applications.
>
> > A better solution would be the following patch to tzset.c which checks
> > /etc/localtime for modification each time it is called:
>
> If we apply it, whenever we issue time related function, not only
> time(2) but also lstat(2) is issued. Filesystem related operation is
> slow (imagine floppy root fs!). Your request is very rare; most user
> do not want such function performance drop.
>
> > It adds a call to stat() to each call to localtime, but ensures that
> > every program on the system changes when the timezone changes - quite
> > invaluable to those of us who travel with laptops and irrelevant to
> > anyone else. It can be switched off by setting the TZ variable
> > explicitly.
> >
> > If the GNOME clock people can put the inner loop patch at the start of
> > clock.c:update_clock(), this would fix the problem for GNOME clock, but
> > I would prefer to see libc6 fix it globally.
>
> Yes, application modification is the easiest way. And it make sense
> when we imagine for example dynamic locale change. It needs
> application modification.
>
>
> If you want to support dynamic timezone switch eagerly, I think one
> way to improve is adding new environment variable (ex: TZ_UPDATE). If
> TZ_UPDATE is defined, then everytime tzset() checks timezone variable
> through tzset() in each time. However one major drawback is user
> needs to set TZ_UPDATE environment variable before he wants to use
> dynamic timezone switch and before he invo...

Read more...

Revision history for this message
Debian Bug Importer (debzilla) wrote :

Message-ID: <email address hidden>
Date: Fri, 22 Oct 2004 14:10:47 +0900
From: GOTO Masanori <email address hidden>
To: Bruce Allen <email address hidden>, <email address hidden>
Cc: GOTO Masanori <email address hidden>, Ian Redfern <email address hidden>,
 "Sean 'Shaleh' Perry" <email address hidden>, Jeff Bailey <email address hidden>, <email address hidden>,
 <email address hidden>
Subject: Re: Bug#48184: Solution

tags 48184 confirmed fixed-upstream
thanks

At Thu, 21 Oct 2004 23:20:43 -0500 (CDT),
Bruce Allen wrote:
> I filed a glibc bug report about this many months ago, and the maintainer
> fixed it recently. Check glibc buzilla (I think that the home is at
> redhat these days) to confirm.

You're correct. I'm surprised the performance degrade was happened
for "The 0.000001% of the people" (see BZ#154). Jakub was tested with
rpm that called 15,000 times. I investigate more, but I tagged it as
fixed-upstream.

Regards,
-- gotom

Revision history for this message
Matt Zimmerman (mdz) wrote :

*** Bug 10941 has been marked as a duplicate of this bug. ***

Revision history for this message
Jeff Bailey (jbailey) wrote :

Fixed in breezy upload.

Revision history for this message
Matt Zimmerman (mdz) wrote :

*** Bug 16503 has been marked as a duplicate of this bug. ***

Revision history for this message
Debian Bug Importer (debzilla) wrote :
Download full text (30.3 KiB)

Message-Id: <email address hidden>
Date: Fri, 05 Aug 2005 03:29:25 -0700
From: GOTO Masanori <email address hidden>
To: <email address hidden>
Subject: Bug#48184: fixed in glibc 2.3.5-3

Source: glibc
Source-Version: 2.3.5-3

We believe that the bug you reported is fixed in the latest version of
glibc, which is due to be installed in the Debian FTP archive:

glibc-doc_2.3.5-3_all.deb
  to pool/main/g/glibc/glibc-doc_2.3.5-3_all.deb
glibc_2.3.5-3.diff.gz
  to pool/main/g/glibc/glibc_2.3.5-3.diff.gz
glibc_2.3.5-3.dsc
  to pool/main/g/glibc/glibc_2.3.5-3.dsc
libc6-dbg_2.3.5-3_arm.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_arm.deb
libc6-dbg_2.3.5-3_hppa.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_hppa.deb
libc6-dbg_2.3.5-3_i386.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_i386.deb
libc6-dbg_2.3.5-3_mips.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_mips.deb
libc6-dbg_2.3.5-3_mipsel.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_mipsel.deb
libc6-dbg_2.3.5-3_powerpc.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_powerpc.deb
libc6-dbg_2.3.5-3_s390.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_s390.deb
libc6-dbg_2.3.5-3_sparc.deb
  to pool/main/g/glibc/libc6-dbg_2.3.5-3_sparc.deb
libc6-dev-ppc64_2.3.5-3_powerpc.deb
  to pool/main/g/glibc/libc6-dev-ppc64_2.3.5-3_powerpc.deb
libc6-dev-s390x_2.3.5-3_s390.deb
  to pool/main/g/glibc/libc6-dev-s390x_2.3.5-3_s390.deb
libc6-dev-sparc64_2.3.5-3_sparc.deb
  to pool/main/g/glibc/libc6-dev-sparc64_2.3.5-3_sparc.deb
libc6-dev_2.3.5-3_arm.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_arm.deb
libc6-dev_2.3.5-3_hppa.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_hppa.deb
libc6-dev_2.3.5-3_i386.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_i386.deb
libc6-dev_2.3.5-3_mips.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_mips.deb
libc6-dev_2.3.5-3_mipsel.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_mipsel.deb
libc6-dev_2.3.5-3_powerpc.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_powerpc.deb
libc6-dev_2.3.5-3_s390.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_s390.deb
libc6-dev_2.3.5-3_sparc.deb
  to pool/main/g/glibc/libc6-dev_2.3.5-3_sparc.deb
libc6-i686_2.3.5-3_i386.deb
  to pool/main/g/glibc/libc6-i686_2.3.5-3_i386.deb
libc6-pic_2.3.5-3_arm.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_arm.deb
libc6-pic_2.3.5-3_hppa.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_hppa.deb
libc6-pic_2.3.5-3_i386.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_i386.deb
libc6-pic_2.3.5-3_mips.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_mips.deb
libc6-pic_2.3.5-3_mipsel.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_mipsel.deb
libc6-pic_2.3.5-3_powerpc.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_powerpc.deb
libc6-pic_2.3.5-3_s390.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_s390.deb
libc6-pic_2.3.5-3_sparc.deb
  to pool/main/g/glibc/libc6-pic_2.3.5-3_sparc.deb
libc6-ppc64_2.3.5-3_powerpc.deb
  to pool/main/g/glibc/libc6-ppc64_2.3.5-3_powerpc.deb
libc6-prof_2.3.5-3_arm.deb
  to pool/main/g/glibc/libc6-prof_2.3.5-3_arm.deb
libc6-prof_2.3.5-3_hppa.deb
  to pool/main/g/glibc/libc6-prof_2.3.5-3_hppa.deb
libc6-prof_2.3.5-3_i386.deb
  to pool/main/g/glibc/libc6-prof_2.3.5-3_i386.deb
libc6-prof_2.3.5-3_mips.deb
  to pool/main/g/glibc/libc6-prof_2.3...

Revision history for this message
Debian Bug Importer (debzilla) wrote :

Message-ID: <email address hidden>
Date: Tue, 16 Aug 2005 10:26:38 -0300
From: Per Olofsson <email address hidden>
To: <email address hidden>, <email address hidden>
Cc: <email address hidden>
Subject: fixed in glibc 2.3.5-3

reassign 309616 libc6
close 309616
merge 309616 48184
thanks

This was really a bug in glibc (#48184) which was fixed in version
2.3.5-3. (Yes, I've tested and verified that it works in ion3 now.)

--
Pelle

Revision history for this message
Martin Pitt (pitti) wrote :

*** Bug 24863 has been marked as a duplicate of this bug. ***

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.