thread tss memory leak fixed for RC_1_34_0

I fixed the memory leak that showed up on windows when using the thread library. The leak indeed was related to tss code (oposite to what I believed before). This also already has been fixed by Peter Dimov in the HEAD branch. However I took a different approach, by having replaced the leaking mutex by a CRITICAL_SECTION whose memory is static, thus is not subject to heap tracking. I did this because in Peters code I see a small chance that TlsFree could get into trouble. The on_process_exit could be called multiple times. E.g. from userland code before end of main _and_ from the tss callbacks. (Of course this could be easily cured by use of another once call.) Also I think it is usefull to be able to set a breakpoint on attached_thread_count to check if all threads (native and boost) have already died when it comes to shutdown. This can be used as an additional debugging aid. (The current BOOST_ASSERT does not work well in this place, and I will try to replace it by something more sensible. Ideas welcome! ) The difference between Bills code and my fix also is somewhat smaller, so I hope giving less chances to regressions. What still is left is the other leaks reported when really using tss. I will try to tackle these with a similar approach. Roland

Roland Schwarz wrote:
I fixed the memory leak that showed up on windows when using the thread library. The leak indeed was related to tss code (oposite to what I believed before).
This also already has been fixed by Peter Dimov in the HEAD branch.
However I took a different approach, by having replaced the leaking mutex by a CRITICAL_SECTION whose memory is static, thus is not subject to heap tracking.
I did this because in Peters code I see a small chance that TlsFree could get into trouble. The on_process_exit could be called multiple times. E.g. from userland code before end of main _and_ from the tss callbacks. (Of course this could be easily cured by use of another once call.)
Actually, according to Richter, a CRITICAL_SECTION *does* dynamically allocate memory, when InitializeCriticalSection() is called. To complicate matters further, it may also create an Event kernel object, when EnterCriticalSection() is called: "There is a small chance that the InitializeCriticalSection() function can fail. Microsoft didn't really think about this when it originally designed the function, which is why the function is prototyped as returning VOID. The function might fail because it allocates a block of memory so that the system can have some internal debugging information. If this memory allocation fails, a STATUS_NO_MEMORY exception is raised. You can trap this in your code using structured exception handling... "You can more easily trap this problem using the newer InitializeCriticalSectionAndSpinCount() function. This function also allocates the memory block for debugging information but returns FALSE if the memory could not be allocated. "Another problem can arise when you use Critical Sections. Internally, Critical Sections use an Event kernel object if two or more threads contend for the Critical Section at the same time... Since contention is rare, the system does not create the Event kernel object until the first time it is required. This saves a lot of system resources since most Critical Sections never have contention. "In a low-memory situation, a Critical Section might have contention, and the system might be unable to create the required Event kernel object. The EnterCriticalSection() function will then raise an EXCEPTION_INVALID_HANDLE exception. Most developers simply ignore this potential error and have no special handling in their code since this error is extremely rare. However, if you want to be prepared for this situation, you do have two options. "You can use structured exception handling and trap the error. When the error occurs, you can either not access the resource protected with the Critical Section or wait for some memory to become available and then call EnterCriticalSection() again. "Your other option is to create the Critical Section using InitializeCriticalSectionAndSpinCount(), making sure that you set the high bit of the 'dwSpinCount' parameter. When this function sees that the high bit is set, it creates the Event kernel object and associates it with the Critical Section at initialization time. If the Event cannot be created, the function returns FALSE and you can handle this more gracefully in your code. If the Event is created successfully, you know that EnterCriticalSection() will always work and never raise an exception. (Always preallocating the Event kernel objects can waste system resources. You should do this only if your code cannot tolerate EnterCriticalSection() failing, if you are sure that contention will occur, or if you expect the process to be run in very low-memory environments.)" -- Programming Applications for Microsoft Windows, 4th Edition by Jeffrey Richter; Microsoft Press, 1999 pp. 278-279 Moshe

Roland Schwarz wrote:
I did this because in Peters code I see a small chance that TlsFree could get into trouble. The on_process_exit could be called multiple times. E.g. from userland code before end of main _and_ from the tss callbacks. (Of course this could be easily cured by use of another once call.)
My original code didn't have TlsFree for this very reason. Anthony Williams added it, arguing that on_process_exit is guaranteed to be called once.

"Peter Dimov" <pdimov@mmltd.net> writes:
Roland Schwarz wrote:
I did this because in Peters code I see a small chance that TlsFree could get into trouble. The on_process_exit could be called multiple times. E.g. from userland code before end of main _and_ from the tss callbacks. (Of course this could be easily cured by use of another once call.)
My original code didn't have TlsFree for this very reason. Anthony Williams added it, arguing that on_process_exit is guaranteed to be called once.
Indeed. Roland has done more work on this part of boost::threads than I, so I defer to his knowledge, but I would like to understand why --- surely users shouldn't be calling on_process_exit. Anthony -- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
participants (4)
-
Anthony Williams
-
Moshe Matitya
-
Peter Dimov
-
Roland Schwarz