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: http://austingroupbugs.net/view.php?id=167 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 ebl...@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
signature.asc
Description: OpenPGP digital signature