failed assertions leave code running behind the message box?
Is there a way to get other threads and timer callbacks to halt while the assertion message box is on the screen We don't want the program state to change between when the assertion happens and when we click Retry to break the debugger.
There are two kinds of timers: message based timers (WM_TIMER), and timer callbacks (TimerProc). If it's a message, it needs to be pumped by the thread receiving the message, and since the thread is at the point of the assert, you are not in danger of getting the message (you can't be in two code locations in your thread at the same time). Timer callbacks should follow the same constraint--they occur in the same thread as the one intended to receive the callback, which you've already suspended.
You haven't specified whether you've created threads with a Win32 API or in .NET. If it's Win32, then you might want to create your own assertion macro that wraps the normal assert plus call a function of your own called SuspendAllThreads(). Assuming you've kept a list of thread handles, you can call the Win32 API SuspendThread on each of them.
You can consult with MSDN for further information. Usually I discover Win32 APIs by searching on something I know, like CreateThread, and spidering from there.
Your version of ASSERT looks like it is from an earlier version of MFC. In MFC 8.0 (VS 2005), I might go about it by redefining the ASSERT macro. I copied the existing MFC definition and added the code in red:
In stdafx.h: extern bool SuspendThreadsOnAssert();
In stdafx.cpp: bool SuspendThreadsOnAssert() { // suspend your threads and timers if necessary. Note that this will require globally-scoping your handles. return true; // continue with assertion }
Actually, what's happening is timers set with SetTimer are getting messages because the AfxMessageBox pumps messages in the background. We're not creating extra threads other than the ones MFC creates in the background. We can't call KillTimer because there are various slow timers in lots of different objects.
failed assertions leave code running behind the message box?
failed assertions leave code running behind the message box?
Novice KT
There are two kinds of timers: message based timers (WM_TIMER), and timer callbacks (TimerProc). If it's a message, it needs to be pumped by the thread receiving the message, and since the thread is at the point of the assert, you are not in danger of getting the message (you can't be in two code locations in your thread at the same time). Timer callbacks should follow the same constraint--they occur in the same thread as the one intended to receive the callback, which you've already suspended.
mika
We just did this (DEBUG only)
#define assert(f) (void) ((f) || (OutputDebugString("Failed Assert: "#f), \
OutputDebugString("\n"), AfxDebugBreak(), 0))
#define ASSERT(f) assert(f)
Olafo
You haven't specified whether you've created threads with a Win32 API or in .NET. If it's Win32, then you might want to create your own assertion macro that wraps the normal assert plus call a function of your own called SuspendAllThreads(). Assuming you've kept a list of thread handles, you can call the Win32 API SuspendThread on each of them.
See http://msdn.microsoft.com/library/default.asp url=/library/en-us/dllproc/base/suspendthread.asp
For timers, perhaps KillTimer
You can consult with MSDN for further information. Usually I discover Win32 APIs by searching on something I know, like CreateThread, and spidering from there.
Brian
Malcolm Walker
Your version of ASSERT looks like it is from an earlier version of MFC. In MFC 8.0 (VS 2005), I might go about it by redefining the ASSERT macro. I copied the existing MFC definition and added the code in red:
In stdafx.h:
extern bool SuspendThreadsOnAssert();
#undef ASSERT
#define ASSERT(f) DEBUG_ONLY((void) ((f) || !::SuspendThreadsOnAssert() || !::AfxAssertFailedLine(THIS_FILE, __LINE__) || (AfxDebugBreak(), 0)))
In stdafx.cpp:
bool SuspendThreadsOnAssert()
{
// suspend your threads and timers if necessary. Note that this will require globally-scoping your handles.
return true; // continue with assertion
}
bounty