unsetenv() patch for TZ
Craig Howland
howland@LGSInnovations.com
Thu Jun 6 21:33:00 GMT 2013
On 07/09/2011 08:19 AM, Corinna Vinschen wrote:
> Re: unsetenv() patch for TZ
>
> On Jul 8 14:24, Howland Craig D (Craig) wrote:
> > The current implementation of _setenv_r() looks to see if the
> > environment
> > variable being set (or changed) is TZ, calling tzset() when it is so
> > that
> > the timezone is automatically kept matching the environment without user
> > intervention.
> >
> > However, _unsetenv_r() does not provide the same feature, likely leading
> > to a problem when TZ is unset.
> >
> > POSIX says nothing about this feature under setenv() and unsetenv(),
> > so it would be possible to make the behavior consistent by either adding
> > to unset or removing from set. However, adding to unset seems far less
> > likely to cause backwards-compatibility problems than removing from set.
> >
> > The attached patch addresses the issue by adding a tzset() call to
> > _unsetenv_r() when TZ is unset.
>
> Thanks for the patch, but I'm wondering if calling tzset() in _setenv_r
> is the right thing to do. I had a look into SUSv4 and it appears that
> the only functions which are supposed to change the timezone information
> are ctime, localtime, mktime, strftime, and an explicit call to tzset by
> the application.
>
> "Appears", because I couldn't find any definitive answer.
>
> Having said that, shouldn't the tzset() call better be removed in
> _setenv_r and called in the affected functions?
>
> Corinna
>
Corinna:
It's been a while, but to return to this since I'm running into it again and
would like to get away from a local workaround:
Good question. But, no, I suggest that it is better to make the addition to
unsetenv() rather than to use your suggestion for footprint reasons (in addition
to my original less-likely-to-cause-backwards-compatibility reason).
If we were to remove tzset() from setenv and add it to ctime(), localtime(),
mktime(), and strftime(), we would be forcing the environment functions to be
linked when any of those 4 functions were called. (They are not now. In
libc/time, only tzset() currently touches an environment function. A simple
grep shows env in strftime, but that is in the regression test driver.) I would
guess that many small applications that want to deal with time do not actually
use environment variables at all. (I certainly do.) Having tzset() called by
unsetenv() and setenv() can equally be claimed to be pulling tzset() in when
perhaps it might not be wanted, but this seems a more likely case than the
former. That is, if you are using environment variables, it seems much more
likely that you'd also be using time functions at the same time than the flip case.
Addressing your SUSv4 comment, I looked at POSIX.1-2013, and partially agree
with your "apparent" comment, although I think that they may have updated with
respect to 2008 it to make it a little more clear.
Firstly, in the definition of TZ: "The contents of the environment variable
named TZ shall be used by the ctime(), ctime_r(), localtime(), localtime_r()
strftime(), mktime(), functions, and by various utilities, to override the
default timezone." Note the "and by various functions" part, which expands your
list to an open-ended one. While this perhaps makes it sound like maybe tzset()
should be called by these, the base requirement is TZ contents, which only
implies tzset().
Next, from the definition of mktime(), "Local timezone information shall be set
as though mktime() called tzset()." Note specifically the "as though," which
seems to be clearly allowing it to not be directly called. Having it embedded
in setenv() and unsetenv() would give the same apparent operation and therefore
meet the requirement.
Additionally, the environment is not required to be thread-safe, so there is not
any kind of timing reason to prefer the use in the environment functions versus
the time functions. For example, if one thread were calling setenv() to change
TZ, it would need to ensure that the setenv() call were complete before a
different thread could call mktime(), regardless of which function calls tzset().
In summary, I think that technically either calling tzset() from the related
time functions or from the environment functions could work properly and be
standard-compliant. But I think that the environment method better fits
newlib's desire for small footprints, and suggest that route.
If you agree, you could apply the patch from
http://sourceware.org/ml/newlib/2011/msg00297.html (which is still valid), but
if the environment method is a must, I'll perhaps work on that in the next week
or two.
Craig
More information about the Newlib
mailing list