No announcement yet.

Midnight Date$/Time$ Freeze

  • Filter
  • Time
  • Show
Clear All
new posts

  • Midnight Date$/Time$ Freeze

    We have developed a process control application using PB/DOS V3.5
    that is now in beta test phase. The hardware environment is
    composed of an 850 MHz all-in-one CPU card running in a microbox
    and using MSDOS V6.22 as the OS.

    While sampling various process channels, a skid-mounted LCD
    updates with the date and time displayed on one line every five
    seconds. The date and time are displayed using the Date$ and
    Time$ system variables. Beta testing has found that the code
    works flawlessly until midnight at which time the application
    stops working and turns into a rotting pumpkin of sorts. We
    don't find any potential memory overwrite or other subtle errors
    that could potentially cause this to occur.

    Has anyone witnessed this sort of problem before? If so, is
    there a recommended fix? Are there any troubleshooting


  • #2
    The zeal for speed can be a bad thing especially when one turns
    off all error checking. Lance and Bob suggested turning all
    error checking back on. I did that and ... viola! At least one
    error has been identified and is being troubleshot. Hence,
    this midnight freeze problem may just be a symptom of the other
    problem(s) identified. No further replies to this post are
    necessary pending resolution of the error check error identi-
    fied by the compiler.



    • #3
      The "midnight freeze" is the classic symptom of badly-written timer
      or delay routines, where the routine is looking for an exact end time
      that is never reached (in this case, probably because it's looking
      for an exact number of seconds after midnight, without considering
      that the count gets reset every midnight).

      Tom Hanlin
      PowerBASIC Staff


      • #4
        Been there, done that with the midnight freeze scenario.
        However, the beta testers have looked at the code and found no
        such smoking gun. Retesting using PB/DOS debugging features
        has also failed to isolate the problem source. The application
        hangs at the midnight turnover while printing the date and time
        system variables. All the code does is fetch and print the date
        and time system variables. It has been confirmed that MSDOS
        adjusts the date and time correctly when midnight passes.

        Any help or debugging suggestions would be appreciated.



        • #5
          It would appear that the only thing freezing at midnight was my
          brain. A slow review of the offending code section isolated with
          the help of PB/DOS debugging capabilities revealed the following
          code snippet:

          while Timer - StartTime < 5.0 ...

          Since Timer resets at midnight, the while clause became true for
          a very long time. Hence, the application was appearing to hang
          but was actually looping. Tom Hanlin hit the nail on the head
          when he commented on badly-written timer modules. If the shoe
          fits, one must wear it. It's tough to kick against the goads.
          Thanks for the prodding, Tom.



          • #6
            Greetings --

            Unless proven incorrect, a likely suspect is as follows ..

            The usual day as we human beings experience it is 24 hours -OR- 1,440 Minutes -OR- 86,400 seconds.

            Part of the computer's built-in time-keeping function is a SECONDS COUNTER.

            Each day at 12 Midnight local time, the SECONDS COUNTER starts a new count -- 0 1 2 3 4 and so on for the next 23 hours, 59 minutes and 59 seconds, by which point the count has reached 86399.

            Right after the 86399th second, it's 12 Midnight and a new day begins. Instead of registering 86400, the counter resets to zero and the process begins anew.

            Figuring out how to get around that is tricky -- I know! I've tried !

            Best solution -- write some kind of routine that anticipates the daily reset of the seconds counter. If you succeed, please share your code with those of us who have been frustrated with our own botched attempts.

            If you're going by the Time$ data, write a correcting routine that is triggered and in effect during the 7-second period when the Time$ string returns "23:59:57" thru "00:00:03".

            ADDITIONAL THOUGHT -- An obvious one to be sure.

            Why didn't the person(s) who design the time-keeping hardware/software built-in to every PC add accessable routines, strings, variables and the like that allow whatever program you write involving use of the PC's internal clock to perform flawlessly WITHOUT having to write hit-or-miss corrections ??

            I know .. Easier said than Done! And so we programmers continue to suffer!

            Right or Wrong .. That's my 2¢¢ents worth!

            Thanx-A-Lot and Enjoy, Frank -- My PB

            [This message has been edited by Frank Ferrell (edited December 04, 2003).]


            • #7
              A safe generic approach watches for changing times, rather than specific times.
              SUB MyDelay (BYVAL iSeconds AS INTEGER)
                  DIM iTimer AS LONG
                  DO WHILE iSeconds > 0
                      iTimer = INT(TIMER)
                      DO WHILE iTimer = INT(TIMER)
                          ' update display or whatever
                      DECR iSeconds
              END SUB
              The routine as presented is not 100% accurate, since we round off the time
              using INT. If more accuracy is required, the routine can be rewritten to suit.

              Tom Hanlin
              PowerBASIC Staff


              • #8
                I normally check if the Time is less than the time spent and jump around,
                or check if TIMER is within the few seconds of midnight and do the
                routine for those few seconds until we are back to normal.



                • #9
                  tsec0 = Timer                        ‘ time base 
                  ' do stuff
                  tsec = Timer
                  If tsec < tsec0 Then tsec = tsec + 86400   ‘ went past midnight
                  Politically incorrect signatures about immigration patriots are forbidden. Searching “immigration patriots” is forbidden. Thinking about searching ... well, don’t even think about it.


                  • #10
                    Yes Mark ..

                    Other thoughts are important here. RANDOMIZE the TIMER at the start
                    of the program. Plus remember that maybe today you are running this
                    in pure DOS. But tomorrow. perhaps you or even today some other user
                    may be running this in a multi-tasking program. Unless things have
                    changed since I wrote my code libraries for all this many years ago
                    when WIN95 was first coming out and OS/2 was then my choice of multi-
                    taskers, memory says it is absolutely necessary to make sure that you
                    provide time-slice release protection in your code for both keyboard
                    I/O and the TIMER loop as well, particularly if you try to use the
                    SLEEP function in the middle of all this loop stuff.

                    I think you will find this whole issue of roll past midnight is really
                    an extension of the entire business of delay-until logic. In what may
                    be the simplest form, it is a requirement to wait a number of seconds
                    for a key to be depressed, then break out of the keyboard I/O mode.
                    INKEY$, SLEEP and so on, at least in my experience, all clobber the
                    CPU for time slices. Thus, if you want to plan for the future or for
                    any present multi-tasking use of the PB 3.5 experience, you start with
                    this issue of time slice releasing at the lowest level of the keyboard
                    I/O. That means tailoring your keyboard response through a common low-
                    level standard library which includes the time slice releasing!

                    You then call for all keyboard operations via that library. You design
                    it so that you pass a parameter to a SUB or FUNCTION which designates
                    the standardized wait time for this or that.

                    Suddenly, you also have a commonly available wait-time function which
                    is a pure delay item as well! If there is no keyboard I/O during the
                    wait time, then the routine to capture a time slice enabled single byte
                    is now able to be run beautifully in a DOS application under OS/2, or
                    DESQVIEW or WIN95/98 and so on.

                    But at the same time, you can also expand this time slice released loop
                    into a wait until a given time has passed! And there, the technique you
                    just posted, Mark, fits right into this standardized library function for
                    simple keyboard I/O. If you need twenty minutes and need to keep track of
                    roll past mindnight, your 86,400 figure is exactly the way to do this. If
                    more than one day is involved, you have to increment a day counter
                    as well in the escape sequence decision tree list.

                    But wait! There's more! Just like the TV commercials on TV, groan. Here
                    is what my code looks like for each keystroke in my standard I/O library
                    that has been built for this with OS/2 and WIN and so on:

                      IF ISTRUE BIT(pbvHost, 8%) THEN '   In WIN environment
                         ! push DS
                         ! mov AX, &H1680
                         ! int &H2F
                         ! pop DS
                      ELSE '                      Not in a WIN environment
                         ! push DS                ; Save DS for PowerBASIC
                         ! mov AX, &H8600         ; Place function $AH68in AX
                         ! mov CX, &H00           ; Use less than 1000 MS delay
                         ! mov DX, &H0A00         ; Try &H0A00 for a delay in DX
                         ! int &H15               ; Call timer interrupt
                         ! pop DS
                      END IF
                      Z0$ = INKEY$ '                      Now look at keyboard!
                      IF UseMouse THEN '                  Mouse is in use
                         DMQ% = 0 '                       Null button flag
                         MsStatus Button%, Row%, Column% '        Call mouse status
                         IF Button% = 2 THEN '            Not right drag operation
                    Hey! What's that UseMouse deal starting there? Aha, more insight is
                    needed. You have to provide for what is done, sooner or later, in
                    the mouse world too. So you might as well use this same standardized
                    lowest level of what will EVENTUALLY wind up somewhere in the middle
                    of this TIMER loop you posted Mark. The rest of the thinking about
                    timed loops, how to control them, and how to be controlled by them
                    in quiet contemplation of what all else is going on in a box is a very
                    large and complex problem.

                    What's 'proper' for my use isn't necessarily 'proper' for anyone else.
                    But what's inside your very correct 86400 unit day-rollover counter
                    takes me five hundred three (503) lines of source code just to clean
                    up what one dirty little INKEY$ will do to a box in multi-tasking at
                    the same time we provide for mouse compatibility! And that 503
                    lines of code is called for EVERY single keyboard I/O stroke in almost
                    EVERY place in all my over 1,300,000 lines of PB source in the suite.

                    Which finally brings me to the last thought about what you posted Mark!
                    Notice that VBOF& long integer PUBLIC variable above and that SMSE!
                    variable? These are DELAY counter transfer variables for the routine.
                    When you posted your loop source, you didn't note to the reader that
                    since the 86400 is larger than a small integer, if that variable isn't
                    made into something other than a small integer, the loop will smash long
                    before midnight! Recall that undeclared otherwise, PB 3.5 makes small
                    integers out of everything like that..

                    At which point long before the fabled stroke of midnight, your first
                    born attempt to put TIMER to use will be carried off into oblivion
                    and it will never pass over into a new bright day! All dry unleavened
                    humor of course here!

                    Forgive me for expanding your few line post into all this, OK? What I
                    really wanted to do was to try to provide the insight into how to plan
                    all this as a true lowest level concept for the code, which would survive
                    and keep running into eternity, and never raise an eyebrow for the CPU
                    king of everything while the kingdom keeps running smoothly ..

                    GDRFC here!

                    Mike Luther
                    [email protected]
                    Mike Luther
                    [email protected]


                    • #11
                      Say you're in the Windows environment. Doesn't Windows
                      handle the timeslices? When would you need to use
                      ! push DS     
                      ! mov AX, &H1680     
                      ! int &H2F     
                      ! pop DS
                      ? What does it do?
                      Politically incorrect signatures about immigration patriots are forbidden. Searching “immigration patriots” is forbidden. Thinking about searching ... well, don’t even think about it.


                      • #12
                        Gives the WIN op system time to go do other things instead of just
                        going instantly back and trying for keyboard I/O over and over again
                        when that takes priority the way the system is designed. So as I
                        think I learned from far earlier contributions on this same issue here.

                        We are talking about running PB 3.5 programs in a multi-tasking system,
                        not Win programs produced by the PB tools for that. PB 3.5, and, in
                        fact, even the PB IDE for PB 3.5, when run under certain environments
                        in multi-tasking, hog the CPU in a massively active loop that keeps
                        polling for I/O. This I/O can come from keyboard polls, comm port
                        related issues, and so on. This happens in such a way that there is
                        no time slice releasing for any other application which is running on
                        such a multi-tasking system as well. If the problem arises from how
                        the executable is put together, from however the core code does the
                        port I/O work that results in this, then the only way to break it may
                        be to force an assembly language snip into the code that is designed
                        in such a way as to break up the loop causing the damage.

                        PB's IDE for DOS, for example, is coded the way it is as delivered by
                        the crew at PB. It is controllable with TAME330 for time slice release
                        work in a DOS-VDM in OS/2, but what it takes is in direct opposition to
                        the techniques which are required for executables compiled with PB 3.5
                        for DOS on which you are working! Thus when in de-bug use mode, the
                        operator screen trashes the CPU for time slice releasing, when the
                        running program being debugged does not. If you fix the issue for the
                        PB IDE interface, the running code you are de-bugging smashes the CPU,
                        without the submitted assembler snip in there to clean it up anyway.

                        On the level of code which results from PB 3.5 applications made for DOS,
                        if, for example, I make a simple program which is using INKEY$ in a loop
                        or SLEEP in PB 3.5, and run it in WIN-95 or WIN-98, the DOS program,
                        not an actual WIN version from PB's WIN tools, takes so much CPU time
                        looking over and over again for I/O, that there is little comparative
                        CPU action time available for anything else. I'm not saying that there
                        is anything bad with PB in the way it is coded. Designing code for a
                        DOS application which may never run in a multi-tasking environment, can
                        be a far different thing, as to optimization of the compiler product, than
                        code for DOS that are to be used in multi-tasking systems. There are
                        different goals involved here, OK?

                        But if it does hog a CPU, that's likely to go completely un-noticed by
                        many people still working with PB for DOS, in that many would never dream
                        of running half a dozen PB for DOS applications at the same time on the
                        same box, all mixed with twenty or thirty other complete TCP-IP, full
                        networked file service, real-time comm applications and dedicated mini-
                        process server operations on a server-server template used here. We are
                        not talking client server. My OS/2 box that is doing all this, if I
                        look at the open files total on the box, for example has over 600
                        concurrent files open at the same time, which is a far cry from what would
                        ever be though about, for CPU access time, on a pure PB 3.5 compiled
                        excuatable for good old DOS. There are many improvments today!

                        Programs compiled without some attention for this in PB 3.5 for DOS are
                        not the only way this happens. There are MANY other examples of this
                        kind of bad behavior in multi-tasking operating systems. In fact, there
                        are several tools which are available to help release time slices when
                        these ill-mannered programs are used. It may not be at all possible to
                        get anything done about a particular program needed which bashes the
                        CPU in this way. An example of one of these which is frequently used in
                        the OS/2 world for running these problem programs in DOS-VDM's and also
                        in WIN-3 use for time-slice releasing is the little TAME330 utility. But,
                        in answer to your sepcific question, the assemble that you see will let
                        the CPU go ahead and work with other applications so that it isn't needed
                        to use these special tools in many cases, as far as I know it.

                        I have not the faintest idea what will happen with these techniques of
                        using time slice releasing code as in what I posted with WIN-XP and
                        later code. There are a number of other issues for printing, other
                        direct hardware access things which would be problems for my own stuff
                        if I wanted to run it there. I'd like to know the answer to that, but
                        although I have a fully valid copy of CONNECTIX for OS/2 that will let
                        me run even XP in a complete isolated GUEST session under OS/2 safely,
                        I don't have the time or CPU horsepower at the moment to even try it.

                        There is a whole section of discussion on this assembly language code
                        snip business to gain time slice releasing for PB 3.5 for DOS stuff
                        that has gone on here in the PB Forums. Lance and a number of others
                        have contributed greatly to help gain control over this which a search
                        of the Forum should produce.

                        I'd be very happy to have someone else be able to contribute to any
                        specific WIN-XP assembler technique to determine that an executable
                        was operating under that platform. There are a number of conditional
                        compliation or source code switches which would, I think, offer some
                        other ways of handling running PB 3.5 applications cross-platform if
                        anyone could help figure out how to spot this.

                        Mike Luther
                        [email protected]
                        Mike Luther
                        [email protected]