Some people think that the usage of SuspendThread or TerminateThread is very useful.
But if you do this, you will get many, many problems…
You should NOT use Suspend/ResumeThread to do thread synchronization!
Mainly these functoions are pressent for debugging purpose. See MSDN documentation
See documentation for SuspendThread :
This function is primarily designed for use by debuggers It is not intended to be used for thread synchronization.
The documentation for TerminateThread is even worser!
If you use these function you can easily dead-lock your program. Here is just a simple example:
#include #include #include unsigned __stdcall thread(void*) { while(1) { printf(“t”); } } int main() { unsigned dwThreadId; HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, thread, NULL, 0, &dwThreadId); while(1) { SuspendThread(hThread); printf(”.”); ResumeThread(hThread); } return 0; }
So please, never ever call Suspend/TerminateThread (expect if your write an debugger).
The trackback url for this post is http://blog.kalmbachnet.de/bblog/trackback.php/6/
Today I want to list all function in the CRT (VC7.1) which are affected by thread-synchronization. If you use such a function after you suspended a thread (which also uses this function (or functions which uses the same critical section) at the time you suspended it) you will sometimes produce an deadlock.
In the C-Runtime the usage of thread synchronizing via Enter/LeaveCriticalSection is very high (in the multithreaded version; be aware tht the VC8 only supports the multithreaded version of the CRT!). A list of some locks is in mlock.c. In the following I will list the functions which are affected by the given lock-entry.
_SIGNAL_LOCK: raise and internally in "ctrlevent_capture" which is registered via SetConsoleCtrlHandler
_IOB_SCAN_LOCK: _fcloseall, _flushall, fflush, _rmtmp, _setmaxstdio, and via _getstream: _tfdopen, tmpfile
_TMPNAM_LOCK: _ttempnam, tmpfile
_CONIO_LOCK: _cgets, _cgetws, _cputs, _cputws, _getch, _getche, _getwch, _getwche, _kbhit, _ungetch, _ungetwch, _putch, _putwch
_HEAP_LOCK: operator new, operator delete, malloc, realloc, free, calloc, _expand_dbg, _free_dbg, _realloc_dbg, _msize_dbg, _CrtCheckMemory, _CrtSetDbgFlag, _CrtDoForAllClientObjects, _CrtIsMemoryBlock, _CrtMemCheckpoint, _CrtMemDumpAllObjectsSince, _set_new_handler, _heapadd, , _heapchk, _heapmin, _heapwalk, and all other functions which are allocating memory (so you can assume all functions as affected)
_UNDNAME_LOCK: TODO
_TIME_LOCK: TODO
_ENV_LOCK: TODO
_EXIT_LOCK1: TODO
_POPEN_LOCK: TODO
_LOCKTAB_LOCK: TODO
_OSFHND_LOCK: TODO
_SETLOCALE_LOCK: TODO
_MB_CP_LOCK: TODO
_TYPEINFO_LOCK: TODO
_DEBUG_LOCK: TODO
_STREAM_LOCKS: TODO
The trackback url for this post is http://blog.kalmbachnet.de/bblog/trackback.php/16/
For all people who still belive that calling SuspendThread or TerminateThread is not so bad, I want to show that in an simple win32 app, we already have *19* critical sections which might produce an deadlock if you call these function in the wrong time.
Here is the ouput of windbg on an empty win32-console app:
0:000> !locks -v CritSec ntdll!RtlCriticalSectionLock+0 at 7C98C0A0 CritSec ntdll!DeferedCriticalSection+0 at 7C98C080 CritSec ntdll!LdrpLoaderLock+0 at 7C98C0D8 CritSec ntdll!FastPebLock+0 at 7C98E4C0 CritSec ntdll!RtlpCalloutEntryLock+0 at 7C98E4A0 CritSec ntdll!PMCritSect+0 at 7C98DE40 CritSec ntdll!UMLogCritSect+0 at 7C98DE20 CritSec ntdll!RtlpProcessHeapsListLock+0 at 7C98C2E0 CritSec +140608 at 00140608 CritSec +240608 at 00240608 CritSec +250608 at 00250608 CritSec kernel32!BaseDllDirectoryLock+0 at 7C883700 CritSec kernel32!BaseDllRegistryCache+18 at 7C883078 CritSec kernel32!gcsNlsProcessCache+0 at 7C883740 CritSec kernel32!gcsTblPtrs+0 at 7C883360 CritSec kernel32!DllLock+0 at 7C8836A0 CritSec kernel32!ExeNameCriticalSection+0 at 7C8833C0 CritSec kernel32!gcsAppCert+0 at 7C883860 CritSec kernel32!gcsAppCompat+0 at 7C8837A0 Scanned 19 critical sections
The trackback url for this post is http://blog.kalmbachnet.de/bblog/trackback.php/17/