Spot the Defect!

Spot the Defect!

  • Comments 17

At Microsoft we have an internal email list called "Spot the Defect" -- people mail around buggy code they've discovered and we compete to see who can find the most problems with it.  It's fun, and you learn a lot about what other people consider bugs -- everything from security holes to lying comments!

 

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();

    }

    return S_OK;

}

 

  • Darn, I've probably got some of those never-waits/waits-forever bugs in a product. We have a library for adapting DOS applications written for a Symbol Series 3000 hand-held terminal to Windows CE devices without the Console component (e.g. Pocket PCs). Apart from some small areas relating to barcode scanning, everything runs on the same thread - the user's application and the GUI. To keep it responsive, we use ::MsgWaitForMultipleObjects whenever the user's code performs a sleep operation. I can tell you from experience that the Windows CE version of MsgWaitForMultipleObjects _does_ require at least one wait handle. So I wait on the result of ::GetCurrentThread(), which should never be signalled (that would of course indicate that the thread had completed...)
  • The formula (begin <= current && current < end) would eliminate the infinite loop problem.

Page 2 of 2 (17 items) 12