[comp.windows.ms] Screen Peace, MS-DOS, and the system date

bert@helix.nih.gov (Bert Tyler) (12/05/90)

> >After some testing, apparently there is a bug with screenpeace.
> >If you were to leave your computer on over the weekend without touching
> >it until monday (i.e., leave it friday afternoon, and come in monday)
> >, the date would be wrong. It would say Saturday. 
>
> This is not a bug with ScreenPeace. It is a bug with MS-DOS.
>
> The bug is that if you do not query the time for two date changes,
> only one date change will occur. The problem results because when the
> timer interrupt, keeping track of seconds passing, wraps around from
> 2359 to 0000, a flag is set to indicate that the date should be
> incremented. The date is not actually incremented until you actually
> check the time...
> 
> One fix would be to leave the windows Clock running which should query
> the time occasionally and prevent this problem. 

Actually, this "fix" could only make the problem worse.
 
We ran into this symptom here at NIH with our 3+Mail<->BITNET "gateway"
program, which runs 24 hours a day - periodically, the system date
wouldn't change, even though the time-of-day clock was still accurate.
 
I wrote a small test program which simply ran a tight loop invoking
interrupt 1Ah (AX = 0) to read the time-of-day clock, and found that
this program reliably prevented the system date from incrementing.
The logic in that interrupt returns not only the time of day, but a flag 
indicating whether the date has changed since the last time this
interrupt was invoked - a flag that is only returned *once* each day.
MS-DOS uses this flag as an indicator to update the system date.
If an application program invokes this interrupt shortly after midnight,
the application program sees that flag - and MS-DOS, when *it* gets
around to checking the time, doesn't.

We traced our immediate problem down to the fact that we had our screen
display package showing (and constantly updating) the time-of-day on
the screen.  We already had a ten-second delay loop in the program
(we didn't want to burden the server more than we had to), so I added
some logic that checks the time at the start of each delay loop - and
if it's after 11:59:30PM, calculates how many cycles through a nested
"for{}" loop burns up one second and promptly invokes it sixty times,
preventing the screen display package from getting control again until
it is safe.

It's known around here as the "Cinderella function".

fpa@qualcomm.com (Franklin Antonio) (12/06/90)

In article <710@nih-csl.nih.gov> bert@helix.nih.gov (Bert Tyler) writes:
> somebody wrote...
>> >After some testing, apparently there is a bug with screenpeace.
>> >If you were to leave your computer on over the weekend without touching
>> >it until monday (i.e., leave it friday afternoon, and come in monday)
>> >, the date would be wrong. It would say Saturday. 
>>
>Actually, this "fix" could only make the problem worse.
> 
>I wrote a small test program which simply ran a tight loop invoking
>interrupt 1Ah (AX = 0) to read the time-of-day clock, and found that
>this program reliably prevented the system date from incrementing.

Your tried to fix the problem at the wrong level.  The only way to make
sure that DOS gets the correct info from BIOS 1A is to NEVER call this
function yourself.  Let DOS do it.  If you want to ensure that you never
cross two midnights without DOS doing a BIOS 1A call, and thereby eliminate
the date bug, you can do it easily by running a program that does just 
about any DOS call in a loop.  For example, you can do the DOS call that
returns time of day, or any function that causes same to be called.  You can 
throw away the result if you like.


>We traced our immediate problem down to the fact that we had our screen
>display package showing (and constantly updating) the time-of-day on
>the screen.  We already had a ten-second delay loop in the program
>(we didn't want to burden the server more than we had to), so I added

You didn't mention what this screen display package does in this ten
second loop, but my guess is that it doesn't do any DOS calls.  Any
program that sits in a loop without doing any DOS calls longer than
two midnights causes the problem.  Of course, if your program does BIOS 1A
calls to get time in this loop, then you've got TWO problems!

>some logic that checks the time at the start of each delay loop - and
>if it's after 11:59:30PM, calculates how many cycles through a nested
>"for{}" loop burns up one second and promptly invokes it sixty times,
>preventing the screen display package from getting control again until
>it is safe.

it just doesn't have to be this complicated.