In the mid 90s I worked for a small ISV that wrote at GIS that ran on windows 3.1 (a 32 bit operating system that ran 16 bit processes (that could have 32 bit code segments))<p>One of our customer required perfect uptime, which was a problem with the GetTickCount wraparound described here<p>Our solution was to run under NuMega SoftICE [1] and once a month, or so, dispatch an engineer to the customer to simultaneously patch the kernel value for the tick count and also the expected value in our software (and also clean up various handle based cruft)<p>This worked for years. Unfortunately the engineer in question was also an alcoholic, so a particularly spectacular bender spoiled an approx 3 year uptime<p>[1] <a href="https://en.wikipedia.org/wiki/SoftICE" rel="nofollow">https://en.wikipedia.org/wiki/SoftICE</a>
There's a repo from danluu, collecting such debugging stories [1]. I've had my own peculiar bug: "Script crashes before 10 a.m." [2]<p>[1] <a href="https://github.com/danluu/debugging-stories">https://github.com/danluu/debugging-stories</a><p>[2] <a href="https://darekkay.com/blog/script-crashes-before-10/" rel="nofollow">https://darekkay.com/blog/script-crashes-before-10/</a>
Interesting bug, but I don’t like the fix.<p>Most computers are 64 bits for decades now. It takes same resources to add/subtract/compare int64 compared to int32. No reason to use 32-bit integers for time, when I write C++ I use GetTickCount64() API introduced in Vista.<p>The C# equivalent is Environment.TickCount64, but there’s no need because unlike many other languages, C# standard library comes with a good support for dates, times, and time intervals. Instead of integers for elapsedInterval and requiredInterval variables, I prefer TimeSpan type. Safer, more readable, and potentially higher resolution because TimeSpan keeps int64 number of 100 nanoseconds ticks.
The bug depends on system clock, but it's a bit of a stretch to say that it depends on moon phase.<p>Unless they were using that system to play NetHack:<p><a href="https://nethackwiki.com/wiki/Time#Moon_phase_and_date" rel="nofollow">https://nethackwiki.com/wiki/Time#Moon_phase_and_date</a>
Reminds me of this "We can't send mail more than 500 miles" story - <a href="https://web.mit.edu/jemorris/humor/500-miles" rel="nofollow">https://web.mit.edu/jemorris/humor/500-miles</a>
I thought this was a reference to the old "phase of the moon" bug entry in the Jargon file[0] and it was very confusing to see it marked 2021. Still, good bug!<p>0: <a href="http://www.catb.org/jargon/html/P/phase-of-the-moon.html" rel="nofollow">http://www.catb.org/jargon/html/P/phase-of-the-moon.html</a>
I strongly believe that "having the two fields get initialized to Environment.TickCount" is the correct fix and using unsigned arithmetic is just a workaround. If you save the time of some event in some field, you either need to initialize that field with current time, or have special processing of "value not set" everywhere it is used, otherwise you're almost guaranteed to have some hard to debug problem somewhere in the long run.
Another interesting debugging story - <a href="https://news.ycombinator.com/item?id=32709045">https://news.ycombinator.com/item?id=32709045</a>
<i>currentTimeMs is Environment.TickCount, which in this case happens to be negative.</i><p>It's worth noting that GetTickCount() is documented as returning an <i>unsigned</i> count, and unless you really need to time intervals > ~49 days to millisecond accuracy, everything works as expected with modulo arithmetic.<p>Windows' AppVerifier has an option that causes GTC to rollover much sooner, specifically to test for such bugs.
Cool case! Always really interesting to read about other people's debugging cases and strategies. I can also 100% recommend <a href="https://www.whyprogramsfail.com/" rel="nofollow">https://www.whyprogramsfail.com/</a>, a book which looks at the theory behind writing correct software.
I was hoping this would be a post about some bug that manifested itself in scada systems for tidal gauges or something actually affected by the physical position of the moon.