Fabulous Adventures In Coding
Eric Lippert is a principal developer on the C# compiler team. Learn more about Eric.
I love playing Spot the Defect. Here is the code for the WScript.Sleep method with the comments removed and some serious bugs added. You'll note that this code has all the required features I mentioned in my previous post. We go to sleep in one-second (or less) intervals, and tell the operating system to wake us up if COM posts a message to the message queue, because there might be an event handler to dispatch. We also check to see if the host recorded a script error (either due to an event handler or due to the script timeout firing) so that we can abort the sleep. This way we never keep the script alive more than a second after it was shut down due to error.
What bug did I add?
HRESULT CWScript::Sleep(long Time)
{
const DWORD TimerGranularity = 1000;
if (Time < 0)
return E_INVALIDARG;
DWORD StartTickCount = ::GetTickCount();
DWORD EndTickCount = StartTickCount + Time;
DWORD CurTickCount = StartTickCount;
while(CurTickCount < EndTickCount)
MSG msg;
DWORD CurWaitTime = (DWORD)(EndTickCount - CurTickCount);
if (CurWaitTime > TimerGranularity)
CurWaitTime = TimerGranularity;
::MsgWaitForMultipleObjects(0, NULL, TRUE, CurWaitTime, QS_ALLINPUT | QS_ALLPOSTMESSAGE);
if (0 != ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
::DispatchMessage(&msg);
if (m_pHost->FErrorPending())
return S_OK;
CurTickCount = ::GetTickCount();
}