Steve Hay wrote on 2011-02-07:
> Steve Hay wrote on 2011-02-07:
>> Steve Hay wrote on 2011-02-04:
>>> William A. Rowe Jr. wrote on 2011-02-04:
>>>> On 2/4/2011 3:49 PM, Steve Hay wrote:
>>>>> It looks like the original environ[] was allocated by msvcr100.dll
>>>> using something other than a function matching the HeapFree()
>>>> function where the crash finally happens. The CRT code is trying to
>>>> free the existing PATH in its environment before setting the new
>>>> value coming from _putenv(), and it is that free that crashes,
>>>> presumably because the APR re-processing of the environ entities
>>>> didn't fool MSVCRT well enough?
>>>>
>>> That makes sense, and it should be easy to make that conditional on
>>> the vc version. Now the question is where were these allocated from
>>> in MSVCR100? Only a trip through the crt sources will help out,
>>> there. Indeed, but looking through the VS2010 CRT source code the
> environment
>>> seems to be initialized in stdenvp.c using _calloc_crt, which should
>>> match the _free_crt call in setenv.c line 211 where it all goes wrong,
>>> so I'm confused why it's crashing. The VS2008 CRT source code looks
>>> the same in this area too.
>>
>> The attached modified version of my original test program no longer
>> crashes, but I'm not sure whether the environment re-processing still
>> achieves what it is meant to.
>>
>> The only change is that it now does the UTF-8 conversion into env and
>> then copies that to _environ, rather than converting into _environ and
>> then copying that to env.
>>
> Sadly, that change is no good: Apache/mod_perl now successfully runs
> with the -DONE_PROCESS option (which it didn't before), but is still
> unable to startup normally -- it fails to spawn the child process:
>
After some more trial and error with this, I've now found that the following
patch gets it working (including a normal Apache/mod_perl setup this time).
I don't know what, if anything, is wrong with the original code (mallocing,
then reallocing memory, then assigning newarr to *retarr), but when the newarr
is copied string-by-string into _environ in the following manner (using the
same method as the CRT source code's own stdenvp.c initializes _environ in the
first place) then it's all ok.
Does anybody have a view on whether there is anything wrong with the current
APR code which perhaps needs to be fixed in this kind of way, or whether this
looks more like a bug in the MS CRT which I could report to Microsoft? (Even in
the latter case, I think the APR code still needs a workaround for the current
MSVCR100.dll behaviour otherwise Apache/mod_perl (and presumably any other
Apache HTTPd module that call putenv()) doesn't run on Vista/2008/Win7 when
built with VS2010.)
diff -ruN httpd-2.2.17.orig/srclib/apr/misc/win32/start.c
httpd-2.2.17/srclib/apr/misc/win32/start.c
--- httpd-2.2.17.orig/srclib/apr/misc/win32/start.c 2007-08-26
17:19:56.000000000 +0100
+++ httpd-2.2.17/srclib/apr/misc/win32/start.c 2011-02-08 12:42:25.259024500
+0000
@@ -46,6 +46,7 @@
apr_size_t newlen;
apr_size_t wsize;
char **newarr;
+ char **env;
int arg;
if (args < 0) {
@@ -85,7 +86,18 @@
newarr[arg] = NULL;
- *retarr = newarr;
+ /* *retarr = newarr; <--- Crashes in VS2010 release mode builds on
Vista/2008/Win7 */
+ *retarr = env = (char **)_malloc_dbg((args + 1) * sizeof(char*),
_CRT_BLOCK, __FILE__, __LINE__);
+ for (arg = 0; arg < args; ++arg) {
+ int len = (int)strlen(newarr[arg]) + 1;
+ *env = (char*)_malloc_dbg(len * sizeof(char), _CRT_BLOCK, __FILE__,
__LINE__);
+ strcpy_s(*env, len, newarr[arg]);
+ env++;
+ }
+ *env = NULL;
+ _free_dbg(newarr[0], _CRT_BLOCK);
+ _free_dbg(newarr, _CRT_BLOCK);
+
return args;
}
#endif