Tcl Source Code

View Ticket
Login
Ticket UUID: 414910
Title: Win2000, putenv, not freeing memory
Type: Bug Version: None
Submitter: nobody Created on: 2001-04-09 15:24:42
Subsystem: 08. Environment Variables Assigned To: davygrvy
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2002-08-29 05:52:23
Resolution: Fixed Closed By: davygrvy
    Closed on: 2002-08-28 22:52:23
Description:
When PUTENV is set on windows 2000, the comment 
appears to be right, but the code doesn't follow 
through.
    /*
     * Watch out for versions of putenv that copy the 
string (e.g. VC++).
     * In this case we need to free the string 
immediately.  Otherwise
     * update the string in the cache.
     */
(environ[index] != p) the buffer is never freed.
User Comments: davygrvy added on 2002-08-29 05:52:23:
Logged In: YES 
user_id=7549

Patch committed to HEAD.

No negative response heard from my eyeball request on the 
core team mailing list, so therefore this gets pushed.

davygrvy added on 2002-08-25 04:16:49:

File Deleted - 29691: 



File Added - 29722: patch.txt

Logged In: YES 
user_id=7549

Jeff, could you have a look at this patch?  It looks ready.

With Dave Welton on the assist, here we go for more.  Now 
tested on NetBSD 1.5.2 (which does copy), and windows 
(makefile.vc) by myself.  It looks good.

davygrvy added on 2002-08-24 08:48:08:

File Deleted - 29669: 



File Added - 29691: patch.txt

Logged In: YES 
user_id=7549

new patch attached with unix/configure.in test added for 
putenv() copying.  Is this ready to be applied?

davidw added on 2002-08-24 03:32:11:
Logged In: YES 
user_id=240

#include <stdlib.h>

#define OURVAR "hola=chau"

int main (int argc, char *argv[], char *environ)
{
    char *foo;
    char *bar;
    foo = (char *)strdup(OURVAR);

    putenv(foo);
    bar = getenv("hola");
    printf("%x == %x\n", bar, strchr(foo, '=') + 1);

}

Is one example of how we could test for a copying putenv.

davygrvy added on 2002-08-24 02:15:14:

File Deleted - 23833: 



File Added - 29669: patch.txt

davygrvy added on 2002-08-24 02:15:13:
Logged In: YES 
user_id=7549

newer patch added.  Assuming that VC++ 7.0 has that 
memory leak fixed, we still have a putenv() that copies.  A 
good assumption, at least.  According to David Welton in 
private email glibc 2.0 - 2.1.1 also has a copy behavior and 
BSD4.4 does as well.  I think it would be wise to add a 
configure test based on behavior rather than glibc versions.

Could someone do this for us?

davidw added on 2002-08-23 09:19:17:
Logged In: YES 
user_id=240

I am seeing this on windows XP as well, just FYI.

davygrvy added on 2002-05-29 06:27:01:
Logged In: YES 
user_id=7549

All this caching makes me sick.  Please rekindle my faith in 
putenv() and what is wrong with the Win32's 
Put/GetEnvironmentVariable(), GetEnvironmentStrings()?

GetEnvironmentVariable() will need 2 calls, if the static buffer 
isn't large enough.  Is this really a speed issue with this 
caching stuff?

davygrvy added on 2002-05-29 06:19:06:
Logged In: YES 
user_id=7549

If this leak is truly caused by the MS runtime, why is
ckrealloc() the originator of the memory blocks as shown
in the trace dumps?

 1e5d1a0 -  1e5d1af       16 @ ..\generic\tclEnv.c 249 
envLeak18
 1e4a4b8 -  1e4a4c5       14 @ ..\generic\tclEnv.c 249 
envLeak18
 1e4a470 -  1e4a47f       16 @ ..\generic\tclEnv.c 249 
envLeak18
 1e4a428 -  1e4a435       14 @ ..\generic\tclEnv.c 249 
envLeak18
 1f99758 -  1f99762       11 @ ..\generic\tclEnv.c 249 
envLeak18
 1e4a688 -  1e4a692       11 @ ..\generic\tclEnv.c 249 
envLeak18
  981930 -   98193d       14 @ ..\generic\tclEnv.c 249 
envLeak18
 1d8c348 -  1d8c35b       20 @ ..\generic\tclEnv.c 249 
envLeak18
  8f05e8 -   8f05fe       23 @ ..\generic\tclEnv.c 249 envLeak18
 1f98b38 -  1f98b42       11 @ ..\generic\tclEnv.c 249 
envLeak18
 1e4a398 -  1e4a3a4       13 @ ..\generic\tclEnv.c 249 
envLeak18
 1e4a3e0 -  1e4a3ec       13 @ ..\generic\tclEnv.c 249 
envLeak18
 1fbfff0 -  1fbfff3        4 @ ..\generic\tclEnv.c 409 
 1fb9070 -  1fb9076        7 @ ..\generic\tclEnv.c 249 
 1e5d868 -  1e5d877       16 @ ..\generic\tclEnv.c 249 
envLeak17
 1e4a100 -  1e4a10d       14 @ ..\generic\tclEnv.c 249 
envLeak17
 1e4a0b8 -  1e4a0c7       16 @ ..\generic\tclEnv.c 249 
envLeak17
 1e4a070 -  1e4a07d       14 @ ..\generic\tclEnv.c 249 
envLeak17
 1f98ca0 -  1f98caa       11 @ ..\generic\tclEnv.c 249 
envLeak17
 1fbf598 -  1fbf5a2       11 @ ..\generic\tclEnv.c 249 envLeak17
  957d08 -   957d15       14 @ ..\generic\tclEnv.c 249 
envLeak17
 1fb90b8 -  1fb90cb       20 @ ..\generic\tclEnv.c 249 
envLeak17
 1fa3378 -  1fa338e       23 @ ..\generic\tclEnv.c 249 
envLeak17
 1f985c8 -  1f985d2       11 @ ..\generic\tclEnv.c 249 
envLeak17
 1e4a7a8 -  1e4a7b4       13 @ ..\generic\tclEnv.c 249 
envLeak17
 1e4a028 -  1e4a034       13 @ ..\generic\tclEnv.c 249 
envLeak17

etc....

davygrvy added on 2002-05-28 06:06:51:
Logged In: YES 
user_id=7549

Just because VC++'s putenv() copies the string and might 
impart it's own memory leak in doing so, might be a seperate 
issue from Tcl not free'ing it's own buffer used for the putenv() 
call.

davygrvy added on 2002-05-28 04:53:04:
Logged In: YES 
user_id=7549

Apply this to stock tclhttpd, and slam it with a few hundred 
hits, then close the server down and read through the onexit 
dump.

Index: doc.tcl
=============================================
======================
RCS file: /cvsroot/tclhttpd/tclhttpd/lib/doc.tcl,v
retrieving revision 1.43
diff -c -r1.43 doc.tcl
*** doc.tcl9 Jul 2001 23:05:19 -00001.43
--- doc.tcl27 May 2002 21:51:00 -0000
***************
*** 858,864 ****
      upvar #0 Httpd$sock data
      set Doc(errorUrl) $data(url)
      set Doc(errorInfo) $ei;# For subst
!     CountName $Doc(errorUrl) error
      DocSubstSystemFile $sock error 500 [protect_text $ei]
  }
  
--- 858,864 ----
      upvar #0 Httpd$sock data
      set Doc(errorUrl) $data(url)
      set Doc(errorInfo) $ei;# For subst
!     CountName $Doc(errorUrl) errors
      DocSubstSystemFile $sock error 500 [protect_text $ei]
  }
  
***************
*** 1118,1125 ****
--- 1118,1139 ----
      # Populate the global "env" array similarly to the CGI 
environment
  
      Cgi_SetEnv $sock $filename pass
+ 
+ ### DAVYGRVY LEAK TESTING
+     global davygrvy
+     if {![info exist davygrvy]} {
+ set davygrvy -1
+ memory onexit onexit.txt
+     }
+     memory tag "envLeak[incr davygrvy]"
+ ### DAVYGRVY LEAK TESTING
+ 
      interp eval $interp [list uplevel #0 \
  [list array set env [array get pass]]]
+ 
+ ### DAVYGRVY LEAK TESTING
+     memory tag ""
+ ### DAVYGRVY LEAK TESTING
  
      if {0} {
  # Duplicate this in the "cgienv" array.

davygrvy added on 2002-05-28 04:40:02:
Logged In: YES 
user_id=7549

_MSC_VER == 1200 for VC6

A check against the actual runtime loaded (msvcrt.dll) might 
be more accurate.  I really don't know how VC++ .NET has 
this fixed.  Is it a new msvcrt.dll or what?  I'm assuming 
MingW uses a broken msvcrt.dll.

hobbs added on 2002-05-28 04:28:44:
Logged In: YES 
user_id=72656

what sort of testing did you do this on?  Is the MSVC version 
check right so that it won't trigger in VS.NET, which 
supposedly has corrected this?

davygrvy added on 2002-05-28 03:42:39:

File Added - 23833: patch.txt

Logged In: YES 
user_id=7549

here's me trying to free it with success.  This does work.

This was the source of a 373 byte leak I was searching for in 
tclhttpd per page hit.  The leak is now down to 27 bytes with 
the patch applied.

davygrvy added on 2002-03-03 22:19:04:
Logged In: YES 
user_id=7549

For an alternate approach, one could consider not using 
_environ at all and expell effort maintaining a cache.  One 
could ask the OS directly with GetEnvironmentString() and 
parse it directly for the entries asked of it.

http://msdn.microsoft.com/library/en-
us/dllproc/prothred_9gs3.asp

We'll need a new platform specific source file.  It might 
impart a performance hit.  The first few entries in the 
string are a bit odd.  They probably have internal meaning, 
but aren't documented.

hobbs added on 2002-03-03 05:50:03:
Logged In: YES 
user_id=72656

As indicated in Bug Q235601 in the MSDN, this is actually a 
bug from Microsoft, so we can't do much to correct it:

http://support.microsoft.com/directory/article.asp?ID=KB;EN-
US;Q235601&LN=EN-US

It may be possible to going around and clean behind the 
scenes in the _environ C array, but that may be (extremely) 
brittle.

davygrvy added on 2001-11-20 08:58:54:
Logged In: YES 
user_id=7549

Um, like what source file is this in?

Attachments: