Notes |
|
(0029268)
|
Brad King
|
2012-04-20 11:30
|
|
CMake modifies its own environment freely because it was written as a single-threaded program intentionally. This is still true for cmake, ccmake, ctest, and cpack.
At some point the Qt dialog became threaded. The cmake-gui application will have to deal with this. Threads other than the one used for configure/generate steps should not modify the environment. |
|
|
(0029269)
|
Brad King
|
2012-04-20 11:33
|
|
|
|
(0029289)
|
Clinton Stimpson
|
2012-04-20 20:29
|
|
The main thread waits for a couple seconds for the configure/generate thread to stop in response to an interrupt. If the thread doesn't finish, it proceeds to quit, because it doesn't want to leave the app hanging there. CMake 2.8.8 greatly improved the interrupt granularity, so its less likely this would happen.
But its easy to produce a hang with something like this
execute_process(COMMAND "cat")
How then should we stop it?
Also, as far as I know, the main thread doesn't use putenv() after the second thread starts. |
|
|
(0029291)
|
Clinton Stimpson
|
2012-04-21 09:45
|
|
|
|
(0029292)
|
Clinton Stimpson
|
2012-04-21 11:40
|
|
Brad, I'm not sure if this is the same thing, but there is a bug in SystemTools.cxx when using putenv() to set environment variables.
To see it the bug, apply this patch
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 846aef5..83f2907 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -39,6 +39,17 @@
#include <cmsys/Glob.hxx>
#include <cmsys/RegularExpression.hxx>
+struct dummy
+{
+ ~dummy()
+ {
+ getenv("A");
+ getenv("Z");
+ }
+};
+
+static dummy mydummy;
+
Then run the single threaded cmake on a CMakeLists.txt that has just this:
set(ENV{MYVAR} "asdfasf")
message("MYVAR=$ENV{MYVAR}")
valgrind reports this:
==26088== Invalid read of size 2
==26088== at 0x5809988: getenv (getenv.c:66)
==26088== by 0x67263D: dummy::~dummy() (cmake.cxx:46)
==26088== by 0x580A4F1: exit (exit.c:78)
==26088== by 0x57EFD94: (below main) (libc-start.c:258)
==26088== Address 0x5c48aa0 is 0 bytes inside a block of size 11 free'd
==26088== at 0x4C276FF: operator delete[](void*) (vg_replace_malloc.c:409)
==26088== by 0x8292E2: cmsys::kwsysDeletingCharVector::~kwsysDeletingCharVector() (SystemTools.cxx:390)
==26088== by 0x580A4F1: exit (exit.c:78)
==26088== by 0x57EFD94: (below main) (libc-start.c:258)
==26088==
==26088== Invalid read of size 2
==26088== at 0x5809988: getenv (getenv.c:66)
==26088== by 0x672647: dummy::~dummy() (cmake.cxx:47)
==26088== by 0x580A4F1: exit (exit.c:78)
==26088== by 0x57EFD94: (below main) (libc-start.c:258)
==26088== Address 0x5c48aa0 is 0 bytes inside a block of size 11 free'd
==26088== at 0x4C276FF: operator delete[](void*) (vg_replace_malloc.c:409)
==26088== by 0x8292E2: cmsys::kwsysDeletingCharVector::~kwsysDeletingCharVector() (SystemTools.cxx:390)
==26088== by 0x580A4F1: exit (exit.c:78)
==26088== by 0x57EFD94: (below main) (libc-start.c:258)
glibc takes ownership of the strings passed in putenv(). We should not clean those up ourselves. |
|
|
(0029293)
|
Clinton Stimpson
|
2012-04-21 11:49
|
|
If I fix it to do
bool SystemTools::PutEnv(const char* value)
{
return putenv(strdup(value));
}
the memory error goes away, but valgrind reports a leak unless I use the --run-libc-freeres=no option.
Can we just change the code to use the preferred setenv() instead? And for Windows, use SetEnvironmentVariable() which is identical. |
|
|
(0029318)
|
Brad King
|
2012-04-23 16:35
|
|
Re 0013156:0029293: IIRC SystemTools::PutEnv came from a library that pre-dated CMake and at the time putenv was used because it was more portable. From the glibc man pages:
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
putenv(): _SVID_SOURCE || _XOPEN_SOURCE
setenv(), unsetenv(): _BSD_SOURCE || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
|
|
|
(0029325)
|
Brad King
|
2012-04-24 11:17
|
|
|
|
(0029334)
|
Brad King
|
2012-04-25 08:42
|
|
|
|
(0029340)
|
Clinton Stimpson
|
2012-04-25 09:56
|
|
|
|
(0029342)
|
Brad King
|
2012-04-25 10:36
(edited on: 2012-04-26 08:57) |
|
Re 0013156:0029340: Thanks. That may address the immediate issue.
Meanwhile I may continue to investigate how complicated it is to set an environment variable portably and without leaking memory.
Re 0013156:0029334: The Windows SetEnvironmentVariable never touches the C runtime environment so getenv does not see the changes (but GetEnvironmentVariable does). Windows toolchains provide only putenv to modify the C runtime environment. Direct modification of the "environ" global is dangerous because of interaction with "wenviron" hidden behind getenv/putenv and wgetenv/wputenv.
Behavior of putenv("A=B") observed by experimentation:
Linux (glibc) putenv references the original memory.
Cygwin putenv references the original memory.
MinGW putenv copies the memory.
MS putenv copies the memory.
Borland putenv references the original memory.
Behavior of putenv("A=") observed by experimentation:
Linux (glibc) putenv STORES empty values, returns 0.
Cygwin putenv STORES empty values, returns 0.
MinGW putenv REMOVES empty values, returns 0.
MS putenv REMOVES empty values, returns 0.
Borland putenv REMOVES empty values, returns 0.
Behavior of putenv("A") observed by experimentation:
Linux (glibc) putenv REMOVES the value, returns 0.
Cygwin putenv REMOVES the value, returns 0.
MinGW putenv IGNORES the call, returns -1.
MS putenv IGNORES the call, returns -1.
Borland putenv IGNORES the call, returns -1.
|
|
|
(0029369)
|
Brad King
|
2012-04-30 09:19
|
|
|
|
(0029373)
|
Clinton Stimpson
|
2012-04-30 15:15
|
|
|
|
(0032025)
|
Robert Maynard
|
2013-01-09 10:55
|
|
Closing resolved issues that have not been updated in more than 4 months. |
|