Follow-up Comment #6, bug #61409 (project make): Now I have a slightly better understanding of the problem, although I had no time to experiment anything yet.
The real problem is in Microsoft UCRT, which has a bug in the code managing the environment. Unfortunately, even if Microsoft will fix the bug tomorrow, we still have to deal with millions of Windows instances which exhibit the bug. And in this respect, all programs that spawn children processes should consider workarounds, including GNU make. If my understanding is correct (based on the explanations I received from someone much more knowledgeable than myself), the problem is related to the way the environment is understood by Microsoft. --- Internally, the "environment" in a Windows process consists of a little more than what you see in the standard C envp array. If you run GetEnvironmentStringsA/W and iterate over it, you'll see the normal environment variables, but also a few other ones, like these: =::=::\ =C:=C:\code\ms-spawn-issue\sources\spawn =ExitCode=00000000 These are special vars that start with an '=' - apparently the include information about things like which directory is the "current directory" on each drive letter. When UCRT's spawn() tries to create a process, it wants to include these extra variables from the current environment (from GetEnvironmentStringsA/W) on top of the variables you provide in the 'envp' parameter. When make starts its subprocesses, it does that by calling CreateProcess() and passing in a string with the desired environment, but it doesn't know/care about this kind of extra variables. So processes launched by make are missing these extra variables in GetEnvironmentStringsA/W. When launching a process with CreateProcess() and passing NULL to the environment parameter, or passing NULL to the envp parameter to spawn, there's no issue (the current exact environment is passed on). But if UCRT's spawn is called in an environment that is missing these extra variables, it crashes. --- So, if make creates sub-processes with a custom environment (i.e. does not pass NULL to inherit the parent), those processes cannot use UCRT to create sub-processes. The same applies to sh.exe which spawns, for example, the compiler, to the compiler who spawns the internal steps, and so on. The workaround is relatively simple. The only known way that is guaranteed to work is to pass a NULL environment, which means to inherit the environment from the parent. This means that instead of creating a custom environment, the parent must temporarily adjust its own environment to match the desired one, spawn the process, and restore the initial environment. I did not check the code used by make, but if it passes a custom environment and not a NULL, its children are affected by this Windows bug. Regarding the question related to UCRT vs MSVCRT, the use of MSVCRT was deprecated about 10 years ago when UCRT was introduced. mingw-w64 already implements UCRT for some time, and it is very likely to become the default in future mingw-w64 releases, since the MSVCRT code has many limitations and is no longer maintained. All recent binary toolchain distributions (both clang and gcc) produce binaries the use UCRT. Thus the suggestion to stick to MSVCRT is not realistic. Sure, you can close the issue, but this will not solve the problem. _______________________________________________________ Reply to this item at: <https://savannah.gnu.org/bugs/?61409> _______________________________________________ Message sent via Savannah https://savannah.gnu.org/