On occasion, we've all faced a situation where we need to check to see if some internal application process has succeeded, or gotten stuck. There are many ways to accomplish this; some better than others. In the old days, folks used loops to count CPU cycles. Of course, as CPUs got faster, this didn't scale all that well. Now you can use myriad combinations of event handlers, semaphores, thread safe flags and threads. Or you can just use the time tested method of hard coding a sleep.

Of course, this requires that you have a decent idea of how long something will take to complete. It also assumes that you know something about the delays that can reasonably be expected in the execution environment.

If it's on your hardware, that may be reasonable. When it's on the customer's hardware in their environment, your ability to accurately guess how long stuff will take decreases exponentially (think solid state disks vs. local physical disks vs. network storage vs. anything in the cloud).

Jerry inherited some installer software written by a former cow-orking cowboy coder named Mike. This software would perform several installation/setup tasks. Each used the same mechanism to see whether or not it had completed.

Specifically, It would spawn a thread that did a sleep for a hard-wired period, and then check to see if the step that was running had completed or not. If not, it reported an error.

Except that it frequently (e.g.: most of the time) reported that the task had hung or failed, when it was simply still (legitimately) running. Mike had made several fixes to this end, but never solved the problem. This annoyed the operations team to no end. Jerry was tasked with figuring out why it would incorrectly flag failures so often.

After some spelunking, Jerry had a headdesk moment when he found Mike's fixes in source control. See if you can spot the problem:

   changeset 374223...
   - _BootloaderController.WaitForInstaller(_Id, timeOut + 10 * 000);
   + _BootloaderController.WaitForInstaller(_Id, timeOut + 20 * 000);

   changeset 374254...
   - _BootloaderController.WaitForInstaller(_Id, timeOut + 20 * 000);
   + _BootloaderController.WaitForInstaller(_Id, timeOut + 30 * 000);

   changeset 374296...
   - _BootloaderController.WaitForInstaller(_Id, timeOut + 30 * 000);
   + _BootloaderController.WaitForInstaller(_Id, timeOut + 60 * 000);