PRB: Error on Win32s: R6016 - not enough space for thread data

Retired KB Content Disclaimer
This article was written about products for which Microsoft no longer offers support. Therefore, this article is offered "as is" and will no longer be updated.
Spawning and closing an application repeatedly succeeds around 60 times,then the spawn fails with this error:
R6016 - not enough space for thread data
The thread local storage (TLS) is not freed by the system.

The failure occurs only if there is another Win32-based application activewhile you are doing the spawns. The message itself is not generated byWin32s. It is generated by the Microsoft C Run-time (CRT) librariesLIBC.LIB and LIBCMT.LIB.
In Win32s version 1.25, TLS indices are freed during module cleanup. TheTLS index is owned by the application's main module, so that it is freedwhen the application terminates. This solves the problem for LIBC andLIBCMT.

There is a similar problem with MSVCRT20.DLL. This DLL version of the CRTallocates a new TLS index each time a process attaches to it. MSVCRT20doesn't free the TLS indices when unloading. The system should free them.If only one application uses MSVCRT20 at a time, then the application canbe spawned successfully up to about 60 times on Win32s version 1.20. OnWin32s version 1.25, there is no limitation.

If there is already an active application that uses MSVCRT20, it is notpossible to spawn and close a second application that uses MSVCRT20 morethan about 60 times under Win32s version 1.25. This is because MSVCRT20allocates a TLS index each time a process attaches to it. Win32s will freeall of the TLS indices only when MSVCRT20 is unloaded.
More information
On Win32s, TLS allocation should be done once and not per process. Eachprocess can use the index to store per-process data, just as a threaduses a TLS index on Windows NT. This is easy to do, because DLL data isshared between all processes under Win32s.

The following example demonstrates how to do the TLS allocation once onWin32s:
   BOOL APIENTRY DllMain(HINSTANCE hinstDll, DWORD fdwReason,           LPVOID lpvReserved)   {       static BOOL fFirstProcess = TRUE;       BOOL fWin32s = FALSE;       DWORD dwVersion = GetVersion();       static DWORD dwIndex;       if ( !(dwVersion & 0x80000000) && LOBYTE(LOWORD(dwVersion))<4 )           fWin32s = TRUE;       if (dwReason == DLL_PROCESS_ATTACH) {           if (fFirstProcess || !fWin32s) {               dwIndex = TlsAlloc();            }            fFirstProcess = FALSE;       }       .       .       .   }				

Article ID: 126709 - Last Review: 06/17/2014 21:48:00 - Revision: 4.0

  • KB126709