This is the mail archive of the cygwin mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: localtime and TZ

On 10/29/2010 03:54 PM, Eric Blake wrote:
> On 10/29/2010 03:44 PM, Ken Brown wrote:
>> While trying to debug a timezone problem in the Cygwin build of emacs, I've come across a difference between Cygwin and Linux in the behavior of localtime with respect to TZ.  Suppose I set TZ, call localtime, unset TZ, and call localtime again.  On Cygwin, the second call to localtime re-uses the previous value of TZ.  On Linux, localtime reverts to giving local information, just as if TZ had never been set.  Here's a Simple Test Case:
>> #include <time.h>
>> #include <stdio.h>
>> extern char **environ;

Also, you should be including <unistd.h> for the declaration of environ,
rather than declaring it yourself.

>> void
>> unset_TZ (void)
>> {
>>   char **from, **to;
>>   for (to = from = environ; (*to = *from); from++)
>>     if (! (to[0][0] == 'T' && to[0][1] == 'Z' && to[0][2] == '='))
>>       to++;
>> }
> Messing directly with environ is your problem.  POSIX says that it is
> only portable to traverse (but not modify) environ's contents, or to
> completely assign a new array to environ.  By going behind cygwin's
> back, and not using unsetenv(), you have violated POSIX and can't expect
> sane results.

In particular:

   If the application modifies the pointers to which environ
    points, the behavior of all interfaces described in the System
    Interfaces volume of POSIX.1-2008 is undefined.

    Conforming applications are required not to directly modify the
    pointers to which environ points, but to use only the setenv(),
    unsetenv() and putenv() functions, or assignment to environ
    itself, to manipulate the process environment. This constraint
    allows the implementation to properly manage the memory it
    allocates. This enables the implementation to free any space it
    has allocated to strings (and perhaps the pointers to them)
    stored in environ when unsetenv() is called. A C runtime start-up
    procedure (that which invokes main() and perhaps initializes
    environ) can also initialize a flag indicating that none of the
    environment has yet been copied to allocated storage, or that the
    separate table has not yet been initialized. If the application
    switches to a complete new environment by assigning a new value
    to environ, this can be detected by getenv(), setenv(), unsetenv()
    or putenv() and the implementation can at that point reinitialize
    based on the new environment. (This may include copying the
    environment strings into a new array and assigning environ to
    point to it.)

    In fact, for higher performance of getenv(), implementations
    that do not provide putenv() could also maintain a separate copy
    of the environment in a data structure that could be searched
    much more quickly (such as an indexed hash table, or a binary
    tree), and update both it and the linear list at environ when
    setenv() or unsetenv() is invoked. On implementations that do
    provide putenv(), such a copy might still be worthwhile but
    would need to allow for the fact that applications can directly
    modify the content of environment strings added with putenv().
    For example, if an environment string found by searching the
    copy is one that was added using putenv(), the implementation
    would need to check that the string in environ still has the
    same name (and value, if the copy includes values), and whenever
    searching the copy produces no match the implementation would
    then need to search each environment string in environ that
    was added using putenv() in case any of them have changed their
    names and now match. Thus each use of putenv() to add to the
    environment would reduce the speed advantage of having the copy.

After page 772 line 25712 section exec, add two new paragraphs:

    Applications can change the entire environment in a single
    operation by assigning the environ variable to point to an array
    of character pointers to the new environment strings.
    After assigning a new value to environ, applications should
    not rely on the new environment strings remaining part of the
    environment, as a call to getenv(), [XSI]putenv(),[/XSI]
    setenv(), unsetenv() or any function that is dependent on an
    environment variable may, on noticing that environ has changed,
    copy the environment strings to a new array and assign environ
    to point to it.

    Any application that directly modifies the pointers to which the
    environ variable points has undefined behavior.

Eric Blake    +1-801-349-2682
Libvirt virtualization library

Attachment: signature.asc
Description: OpenPGP digital signature

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]