Bug 154 - tzset not called frequently enough by localtime() and friends
Summary: tzset not called frequently enough by localtime() and friends
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.3.2
: P2 normal
Target Milestone: ---
Assignee: GOTO Masanori
URL:
Keywords:
: 155 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-05-11 22:01 UTC by Bruce Allen
Modified: 2019-04-10 11:54 UTC (History)
4 users (show)

See Also:
Host: i386-redhat-linux-gnu
Target: i386-redhat-linux-gnu
Build: i386-redhat-linux-gnu
Last reconfirmed:
fweimer: security-


Attachments
Patch for tzset.c (2.3.2 and current CVS) (392 bytes, patch)
2004-05-12 09:15 UTC, Christian Franke
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Bruce Allen 2004-05-11 22:01:55 UTC
Suppose that a daemon logs information every ten minutes using syslog(3).
Part of the syslog output includes a timestamp, in the local time zone.
Now suppose that the user takes the machine (laptop) and flies to a new
timezone, then changes /etc/localtime to reflect the new timezone.  The daemon
(which has not been stopped and is still running) will continue to make syslog
entries using the OLD timezone.

This is because localtime() calls tzset on first invocation to learn the
timezone but then caches that information.  However it's not enough to see if
the TZ variable changes.  If TZ is not set then one also needs to check
/etc/localtime before each call to see if THAT has changed.

See bug number 48184 at http://bugs.debian.org for a similar report.

To reproduce the bug:

(1) unset TZ environment variable in shell
(2) run program below
(3) while program is running, change /etc/localtime to a new timezone.
    Note that localtime printed does NOT reflect this change.

#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main() {
  time_t epochnow;
  struct tm *timenow;	
  
  if (getenv("TZ")) {
    fprintf(stderr,"To demonstrate this bug, you must unset the TZ environment
variable\n");
    return 1;
  }

  while (1) {
    time(&epochnow);
    timenow=localtime(&epochnow);
    printf("Time is %s", asctime(timenow));
    sleep(5);   
  }  
  return 0;
}
Comment 1 Bruce Allen 2004-05-12 01:10:52 UTC
*** Bug 155 has been marked as a duplicate of this bug. ***
Comment 2 Christian Franke 2004-05-12 08:21:24 UTC
To resolve this issue, is would be necessary to call tzset() internally in each
invocation of localtime(). This may be considered as too expensive.

But even if an application calls tzset() itself, glibc does not reload the
timezone info if TZ is unset.

To reproduce this bug, add tzset() to program in comment 0:

 while (1) {
+   tzset();
    time(&epochnow);
    timenow=localtime(&epochnow);

The output will be the same.
Comment 3 Christian Franke 2004-05-12 09:15:13 UTC
Created attachment 74 [details]
Patch for tzset.c (2.3.2 and current CVS)

This patch for tzset_internal() handles the issue if TZ is unset.

See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48184&msg=9 for a patch
handling the TZ=/path/timezonefile case also.
Comment 4 Ulrich Drepper 2004-08-09 07:28:49 UTC
I've made the change to tzset.c.  If TZ is not set some more thorough tests are
performed.  The additional change to tzfile.c I added prevents most of the work
in case the file has not changed.

As for any code which doesn't call tzset all the time: this definitly won't
change.  It's far too expensive.  And for what?  The 0.000001% of the people who
take the laptops on a world tour and expect, e.g., syslog messages with dates
according to the native timezone.  This is not justification enough.  Just
restart your machine.
Comment 5 Jackie Rosen 2014-02-16 16:56:08 UTC Comment hidden (spam)
Comment 6 Mediot Listo 2015-08-27 14:41:31 UTC Comment hidden (spam)
Comment 7 Joshua 2015-11-03 18:10:42 UTC Comment hidden (spam)
Comment 8 Elion 2015-11-20 18:26:31 UTC Comment hidden (spam)