Tcl Source Code

View Ticket
Login
Ticket UUID: c9eb6b0ac01bb8ef96a616c71426a3db4a279bec
Title: ConvertLocalToUTCUsingC fails the first time if TZ is not set
Type: Bug Version: 8.6
Submitter: anonymous Created on: 2015-12-10 12:10:34
Subsystem: 06. Time Measurement Assigned To: nobody
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2016-02-16 21:59:09
Resolution: None Closed By: gahr
    Closed on: 2016-02-16 21:59:09
Description: (text/x-fossil-wiki)
This is with fossil trunk on FreeBSD 10.2-RELEASE-p7 amd64.

If TZ is not set in the environment, the ConvertLocalToUTCUsingC will fail the first time it is called. To avoid this, make sure TzsetIfNecessary() always calls tzset the first time.

<verbatim>
Index: generic/tclClock.c
==================================================================
--- generic/tclClock.c
+++ generic/tclClock.c
@@ -2005,25 +2005,28 @@
 static void
 TzsetIfNecessary(void)
 {
     static char *tzWas = NULL;	/* Previous value of TZ, protected by
 				 * clockMutex. */
+    static char first = 1;	/* First time? */
     const char *tzIsNow;	/* Current value of TZ */
 
     Tcl_MutexLock(&clockMutex);
     tzIsNow = getenv("TZ");
-    if (tzIsNow != NULL && (tzWas == NULL || strcmp(tzIsNow, tzWas) != 0)) {
+    int mod = 	((size_t)tzWas ^ (size_t)tzIsNow) || 
+		((size_t)tzWas & (size_t)tzIsNow && strcmp(tzIsNow, tzWas) != 0);
+    if (first || mod) {
+	first = 0;
 	tzset();
 	if (tzWas != NULL) {
 	    ckfree(tzWas);
+	    tzWas = NULL;
 	}
-	tzWas = ckalloc(strlen(tzIsNow) + 1);
-	strcpy(tzWas, tzIsNow);
-    } else if (tzIsNow == NULL && tzWas != NULL) {
-	tzset();
-	ckfree(tzWas);
-	tzWas = NULL;
+	if (tzIsNow != NULL) {
+	    tzWas = ckalloc(strlen(tzIsNow) + 1);
+	    strcpy(tzWas, tzIsNow);
+	}
     }
     Tcl_MutexUnlock(&clockMutex);
 }
 
 /*
</verbatim>

Using this test driver

<verbatim>
package require clock::iso8601

proc doit {} {
    try {
        ::tcl::clock::ConvertLocalToUTC {
            tzName :localtime
            century 19 
            yearOfCentury 94
            month 11
            dayOfMonth 5
            era CE
            year 1994
            julianDay 2449662
            secondOfDay 0
            localSeconds 783993600} {} 2299161
    } on error msg {
        return "$msg\n[info errorstack]"
    }
}

puts [doit]
puts [doit]

</verbatim>

I get this with a non-patched version of Tcl:

<verbatim>
time value too large/small to represent
INNER {invokeStk1 ::tcl::clock::ConvertLocalToUTC {
            tzName :localtime
            century 19 
            yearOfCentury 94
            month 11
            dayOfMonth 5
            era CE
            year 1994
            julianDay 2449662
            secondOfDay 0
            localSeconds 783993600} {} 2299161} CALL doit
tzName :localtime century 19 yearOfCentury 94 month 11 dayOfMonth 5 era CE year 1994 julianDay 2449662 secondOfDay 0 localSeconds 783993600 seconds 783993600
</verbatim>

And this with a patched version:

<verbatim>
tzName :localtime century 19 yearOfCentury 94 month 11 dayOfMonth 5 era CE year 1994 julianDay 2449662 secondOfDay 0 localSeconds 783993600 seconds 783993600
tzName :localtime century 19 yearOfCentury 94 month 11 dayOfMonth 5 era CE year 1994 julianDay 2449662 secondOfDay 0 localSeconds 783993600 seconds 783993600

</verbatim>
User Comments: gahr added on 2016-02-16 21:59:09: (text/x-fossil-wiki)
Fixed by checkin [38e14f6cc3]