Bug 1608367 - Have default TZ set by system
Summary: Have default TZ set by system
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Fedora
Classification: Fedora
Component: setup
Version: rawhide
Hardware: All
OS: Linux
unspecified
unspecified
Target Milestone: ---
Assignee: Martin Osvald 🛹
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-07-25 12:01 UTC by Jiří Vymazal
Modified: 2022-07-27 07:58 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2022-07-27 07:58:07 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
proof of concept for the VDSO (365 bytes, text/x-csrc)
2019-02-05 15:30 UTC, Matteo Croce
no flags Details

Description Jiří Vymazal 2018-07-25 12:01:21 UTC
Description of problem:
It would be nice if there was always set TZ environment variable to avoid unnecessary syscalls. If left unset for example time() and similar syscalls will call stat() everytime instead of using cached value. I do not know if there is some way for setup to auto-magically set it to correct value, however even simple /etc/localtime will work for the most common use case.

Additional info:
GNU doc for TZ: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html

Comment 1 Jan Kurik 2018-08-14 08:41:21 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 29 development cycle.
Changing version to '29'.

Comment 2 Ondrej Vasik 2018-11-12 06:47:19 UTC
Completely missed that one.
I don't know what you mean by "simple /etc/localtime will work for the most common use case". That file is in binary format and I can't guess the default TZ at the time of setup package installation - as setup is one of the first packages to be installed. 
What I can imagine is profile.d script that will run timedatectl command, parse Time Zone and based on it will set TZ envvar. Not sure if worth effort, though, as this would mean some TZ guess at the start of user session anyway(probably grep + cut). Is this what you expect?

Comment 3 Jiří Vymazal 2018-11-12 10:16:14 UTC
(In reply to Ondrej Vasik from comment #2)
> I don't know what you mean by "simple /etc/localtime will work for the most
> common use case". That file is in binary format 

Yes, that is generally true, however "$ cat /etc/localtime | tail -1" seems to produces sufficient output for time-zone setting.

Comment 4 Miroslav Lichvar 2018-11-12 15:12:53 UTC
The function that causes the stat() call is localtime() and other time conversion functions in glibc, right?

What happens if the admin reconfigures /etc/localtime while the programs are running, or there is a tzdata update? I think that could be an unexpected side effect of this optimization.

Comment 5 Jiří Vymazal 2018-11-12 15:58:04 UTC
(In reply to Miroslav Lichvar from comment #4)
> The function that causes the stat() call is localtime() and other time
> conversion functions in glibc, right?
> 
Yes
> What happens if the admin reconfigures /etc/localtime while the programs are
> running, or there is a tzdata update? I think that could be an unexpected
> side effect of this optimization.
That is unfortunately probable, this optimization would have to be documented so people know to either update the value after updating timezone, however this situation should be quite rare in practice (what are the reasons behind manually changing timezone anyway?).

Comment 6 Matteo Croce 2019-02-05 15:30:14 UTC
Created attachment 1527208 [details]
proof of concept for the VDSO

run it both with TZ set and unset

Comment 7 Matteo Croce 2019-02-05 16:00:54 UTC
Hi all,

the rationale behind this is that the kernel links every binary with a fake library named VDSO[1], as you can see in the ldd output:

$ ldd /bin/cat
        linux-vdso.so.1 (0x00007ffebcdfa000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f5a18ab0000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5a18cb2000)

This library contains a variant of the clock_gettime() and gettimeofday() which gets the time from a readonly shared mem instead of issueing a syscall.
The glibc supports this, but if the TZ environment variable is unset, it does a stat("/etc/localtime"), nullifying the advantage of avoiding a call to gettimeofday().

I have attached a proof of concept to show this, this is a run on a Fedora 29 system with TZ unset:

$ gcc -Wall -O2 time_vdso.c -o time_vdso
$ time ./time_vdso

real    0m6,068s
user    0m1,233s
sys     0m4,835s
$ strace -c ./time_vdso
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100,00   12,664314           2   4999999           stat
  0,00    0,000000           0         6           read
  0,00    0,000000           0         3           close
  0,00    0,000000           0         4           fstat
  0,00    0,000000           0         4           lseek
  0,00    0,000000           0         7           mmap
  0,00    0,000000           0         4           mprotect
  0,00    0,000000           0         1           munmap
  0,00    0,000000           0         4           brk
  0,00    0,000000           0         1         1 access
  0,00    0,000000           0         1           execve
  0,00    0,000000           0         2         1 arch_prctl
  0,00    0,000000           0         3           openat
------ ----------- ----------- --------- --------- ----------------
100.00   12,664314               5000039         2 total

By setting TZ to a good value, the program runs 15x faster:

$ export TZ=Europe/Rome
$ time ./time_vdso

real    0m0,411s
user    0m0,411s
sys     0m0,000s
$ strace -c ./time_vdso
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 17,55    0,000112          16         7           mmap
 13,95    0,000089          22         4           brk
 11,44    0,000073          18         4           mprotect
 10,03    0,000064          64         1           execve
  9,56    0,000061          10         6           read
  8,93    0,000057          19         3           openat
  5,96    0,000038           9         4           fstat
  5,64    0,000036           9         4           lseek
  4,70    0,000030          30         1           munmap
  4,55    0,000029           9         3           close
  4,55    0,000029          14         2         1 arch_prctl
  3,13    0,000020          20         1         1 access
------ ----------- ----------- --------- --------- ----------------
100.00    0,000638                    40         2 total

If the timezone is unknown, it can safely point to a file which describes the time zone, prepended by a colon.
For example, this does the same job without having to specify the zone manually:

$ export TZ=:/etc/localtime
$ time ./time_vdso

real    0m0,414s
user    0m0,410s
sys     0m0,004s


[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/vdso

Comment 8 Matteo Croce 2019-02-11 00:18:12 UTC
On arm64 the difference is more noticeable:

root@macchiatobin:~# uname -a
Linux macchiatobin 5.0.0-rc6 #22 SMP Sun Feb 10 23:54:37 UTC 2019 aarch64 aarch64 aarch64 GNU/Linux

root@macchiatobin:~# time ./time_vdso

real    0m13,849s
user    0m6,089s
sys     0m7,759s

root@macchiatobin:~# export TZ=Europe/Rome

root@macchiatobin:~# time ./time_vdso

real    0m1,463s
user    0m1,463s
sys     0m0,000s

Comment 9 Ben Cotton 2019-10-31 18:43:07 UTC
This message is a reminder that Fedora 29 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora 29 on 2019-11-26.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
Fedora 'version' of '29'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora 29 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior this bug is closed as described in the policy above.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 10 Ben Cotton 2020-02-11 15:40:15 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 32 development cycle.
Changing version to 32.

Comment 11 Ben Cotton 2021-02-09 15:06:21 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 34 development cycle.
Changing version to 34.

Comment 13 Ben Cotton 2022-05-12 16:15:45 UTC
This message is a reminder that Fedora Linux 34 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora Linux 34 on 2022-06-07.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
'version' of '34'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, change the 'version' 
to a later Fedora Linux version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora Linux 34 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora Linux, you are encouraged to change the 'version' to a later version
prior to this bug being closed.

Comment 15 Martin Osvald 🛹 2022-07-27 07:58:07 UTC
I don't think it's a good idea to set a default TZ value globally for all users by setup. No other distro does that (e.g. Suse, Debian). This is not a bug, but a feature.

The reason for stat() calls is to allow for timezone changes. If you don't want that, just set the TZ before running the program or before calling the localtime() to the needed value.

Some background info:

The feature of having /etc/localtime stat() (and if changed also read()) every invocation of localtime() was introduced in REHL6, first attempt to get this behavior appeared in RHEL5:

[Bug 452957 - [RHEL5] localtime() does not handle changes to /etc/locatime]
https://bugzilla.redhat.com/show_bug.cgi?id=452957#c3
~~~
I think it is a bad idea to change this in RHEL5.x, I'm afraid many customers
would be upset by localtime slowdown in an update release.  Just wait for RHEL6.
~~~

Ulrich Drepper explains why it is so and also recommends setting TZ by the user:

[Bug 5184 - strftime stats /etc/localtime too much]
https://sourceware.org/bugzilla/show_bug.cgi?id=5184#c1
~~~
No, /etc/localtime is not touched too often.  All the time functions are
required to check TZ all the time.  Missing that envvar, /etc/localtime is used.
 People who move laptops from one timezone to the other appreciate that.

If this is no problem of yours just set TZ to /etc/localtime and all this will stop.
~~~

Another explanation from Jakub Jelinek:

[Bug 171351 - strftime is unreasonably slow because of tzset]
https://bugzilla.redhat.com/show_bug.cgi?id=171351#c1
~~~
The reason for the stat is to allow for timezone changes.
If you don't want that, you can just use TZ=/etc/localtime or TZ=Europe/Prague
or whatever timezone you want to use.
~~~


Given the information above, I am closing this as WONTFIX.


Note You need to log in before you can comment on or make changes to this bug.