No announcement yet.

A question about Exception handling ???

  • Filter
  • Time
  • Show
Clear All
new posts

  • A question about Exception handling ???

    This is a real technical question :

    Does the machine code generated by the PB compiler deal with
    Exception handling when working with Floating point calculations ?

    The reason is, there is a problem with some Printer drivers, in particular
    HP drivers.

    The following Exception generated by Windows, has something to do
    with the Math Coprocessors handling of exceptions with Floating point

    10h : Coprocessor Error Fault

    I have been researching a problem with a particular Printer driver
    being suspect. When I checked out the MSDN web site, there is a lot
    of mention of particular Printer Drivers (mostly HP drivers) that
    change the Math Coprocessors exception handling , but do not set it
    back to the original setting after the driver loaded. This means
    that if code is designed to handle the exception handling, the loading
    of the HP driver will change how the CPU handles this and the code
    will crash.

    Microsoft suggests unloading the HP drivers and replacing them
    with the closest thing you can find that comes with Windows.

    Has anyone experienced strange exception errors when using HP drivers
    and could someone tell me if the strange behavior of the HP drivers
    would cause a problem for the Floating point code in a PB app ?

    Microsoft list a bunch of its own apps that produce the 10h exception
    error and they blame it on the HP drivers.

    I do know that my HP DeskJet 672C print driver has a serious Resource
    leak in it, but this adds more problems if it is so.

    Chris Boss
    Computer Workshop
    Developer of "EZGUI"

  • #2
    Under what specific conditions does this occur?

    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    mailto:[email protected]


    • #3

      When I call the PrintDlg function to displat the Printer Dialog
      and then afterwards go through a standard procedure for printing .

      After PrintDlg returns and that may be where the code hangs. So far the
      code works fine on all platforms and all printers, except a few Listed
      on a web page I found at the Microsoft web site (Epson Stylus and HP Laser 5L)
      which exhibit this problem.

      The PrintDlg function does load the default printer driver into
      memory and as I said, the code works fine on most PC's and on all
      Platforms (WIN95/98/NT/2000 Pro/ME). Its just the PC's with the suspect
      printer drivers that cause the problem.

      Is there any code (Basic or Assembler) I could execute after calling
      PrintDlg, that would "reset" the Math Coprocessor so it would handle
      exceptions the way the PB compiler expects it too ?

      The cause is suppose to be because the printer driver changes the
      settings for the math coprocessor and forgets to set it back when done.
      If I could simply reset it myself in code, I wouldn't have to worry
      about whether the printer driver did this.

      I rechecked my code and actually I don't there is an immediate Floating point
      code, but only Long (Integer) arithmetic. My code does though
      retrieve values using GetDeviceCaps and then passes those values to
      the API function DPtoLP ! It is possible this function does either
      floating point or it may be dealing with division by zero or some
      other exception.

      It is possible that DPtoLP generates the exception, but only for
      certain Printer drivers.

      The exception error message does list my DLL as the offending DLL
      though and not a system DLL, so it would seem my code causes the
      exception though. The key here is that the code only causes an
      exception with certain printer drivers.

      Chris Boss
      Computer Workshop
      Developer of "EZGUI"


      • #4

        Actually, my code does do some floating point match shortly after
        calling PrintDlg !

        The floating point math is in some procedures I call just before
        executing StartDoc. I display an Abort Dialog and the procedures
        that generate this dialog use some floating point for conversion
        of coordinates.

        The main point is that the problem seems to occur between the
        PrintDlg function call and before StartDoc gets executed. The abort
        Dialog doesn't display as far as I know, so the floating point math
        could be crashing the app, after the PrintDlg call, if the printer
        drivers really do exhibit the problem as stated by Microsoft.

        Chris Boss
        Computer Workshop
        Developer of "EZGUI"


        • #5
          chris, i think i've encountered a problem like this with my
          product. it was very difficult to track, because only a few
          people had this problem, and i couldn't duplicate it on my
          own system. in search for a solution though i read a document
          which talked about printer drivers which mess up the fpu. this
          might be the same document you are talking about.

          my temporary solution was to tell the users to add the following
          lines in their c++ builder code.

          #include <float.h>
          _control87(mcw_em, mcw_em);
          i've had only a couple of people report this problem, and they
          happpened to be using c++. i don't know how you'd do something
          like that in pb itself. even if this problem is not caused by
          pb, i do hope that pb will add the _fpreset() and
          _control87() functions.

          by the way, there was another thread where i mentioned this
          problem. see bizarre math bug
          however, there were several other problems which were also
          discussed, and i'm not sure that this particular one was
          resolved in that discussion.

          daniel corbier
          ucalc fast math parser

          [this message has been edited by daniel corbier (edited february 27, 2001).]
          Daniel Corbier
          uCalc Fast Math Parser
          uCalc Language Builder


          • #6
            From the reports I am receiving from a number of Beta testers,
            the problem is definitely associated with Printer drivers.

            In one situation the Beta tester, replaced his printer driver with
            a new version and the problem disappeared.

            It would seem that if I could do what Daniel suggests (but using PB code)
            after I call the PrintDlg function, the problem would be solved.

            I need to find a way to "reset" the FPU (floating point processor)
            so my PB floating point code won't crash.

            Are there any assembler programmers out there who could show us
            how to reset the FPU using assembler ?

            Would it be possible to do this with straight Basic code (with
            API calls) as well ?

            How would we convert Daniels C code :

            #include <float.h>
            _control87(MCW_EM, MCW_EM);
            to PB code ?

            Chris Boss
            Computer Workshop
            Developer of "EZGUI"


            • #7
              Question :

              Would it be possible to use ON ERROR GOTO to reset the
              FPU ?

              By using an ON ERROR GOTO after the PrintDlg function call and then
              doing some floating point math just to trip the exception, could this work ?

              I would assume that ON ERROR GOTO likely uses some exception handling
              (would that be correct ?) .

              Does On ERROR do exception handling ?

              Would this be useful in reseting the FPU ?

              I am just guessing here, so could someone enlighten me ?

              Chris Boss
              Computer Workshop
              Developer of "EZGUI"


              • #8
                #register none ?

                found the following doc in faq via poffs:

                'forum: frequently asked questions
                'topic: win32: extended-precision and quad integer math (pb/cc 1.0, 2.0 and pb/dll 5.0, 6.0)
                'name: lance edmonds, administrator
                'date: january 14, 2000 03:29 am

                .. no need to repeat the above - see link.

                [this message has been edited by borje hagsten (edited february 28, 2001).]


                • #9
                  I would be very surprised if #REGISTER NONE had *anything* to do with Chris' printer driver problems.

                  Similarly, the 54-bit precision issue is not likely to cause a FPU exception.

                  My suspicions are that the cause of the problem is not a coprocessor exception, but some other problem (such as memory corruption) - probably in the printer driver...

                  ON ERROR works by inserting code into the EXE that tests for run-time error conditions after each "line" of code is executed. An ON ERROR trap is not able to catch an O/S level exception, page fault, or GPF. If #DEBUG ERROR ON is used, then the compiler does add code to test for nul-pointers and array bounds violations.

                  The request for more powerful exception handling is already on the "wish list"

                  PowerBASIC Support
                  mailto:[email protected][email protected]</A>
                  mailto:[email protected]


                  • #10
                    > #include <float.h>
                    > _fpreset();
                    > _control87(MCW_EM, MCW_EM);
                    These can be used by PB.  Declare the functions using Alias.  They
                    are in the msvcrtXX series of dlls.  Try msvcrt20.dll.
                    Declare Sub fpreset Cdecl Lib "msvcrt20.dll" Alias "_fpreset" ()
                    Declare Sub control87 Cdecl Lib "msvcrt20.dll" Alias "_control87" ( Dword new, Dword Mask )
                       /* Show original control word and do calculation. */
                       printf( "Original: 0x%.4x\n", _control87( 0, 0 ) );
                       printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );
                       /* Set precision to 24 bits and recalculate. */
                       printf( "24-bit:   0x%.4x\n", _control87( _PC_24, MCW_PC ) );
                       printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );
                       /* Restore to default and recalculate. */   
                       printf( "Default:  0x%.4x\n", _control87( _CW_DEFAULT, 0xfffff ) );
                       printf( "%1.1f * %1.1f = %.15e\n", a, a, a * a );
                    [This message has been edited by Ron Pierce (edited February 28, 2001).]


                    • #11
                      If you go to the MSDN web site and do a search for the words :

                      Exception 10H

                      You will find a number of pages that refer to the printer drivers
                      being the cause of the problem !

                      Fact #1 The Printer Drivers are the likely cause of this problem.
                      The only time this Exception is generated by my code is when a suspect
                      printer driver was in use. The few times the error occured, the printer
                      drivers in use were ones listed on the following web page as suspect:


                      Next, when you examine a few of those web pages that explain what
                      the Exception 10H means, you come to the conclusion that the FPU
                      is definitely involved.



                      Fact #2 The 10H Exception means : Coprocessor Error Fault
                      and this Exception is generated by Floating point math (when the right
                      circumstances are set).

                      There should be some way to "reset" the math coprocessor to avoid
                      this problem.

                      There should be some way to emulate Daniels suggested C code with
                      PB code (or ASM) :

                      #include <float.h>
                      _control87(MCW_EM, MCW_EM);
                      without resorting to making a call into a Microsoft C runtime DLL.

                      How about you Assembler experts out there ?

                      Can you show us the code in ASM ?

                      [This message has been edited by Chris Boss (edited February 28, 2001).]
                      Chris Boss
                      Computer Workshop
                      Developer of "EZGUI"


                      • #12
                        I decided to follow Ron's suggestion and I did a test:

                        I made the two calls into the msvcrt20.dll as he suggested, right
                        after executing PrintDlg.

                        The results :

                        A Beta tester who found had a problem with multiple printer drivers
                        (some worked and some didn't) says the problem is now gone !.

                        %MCW_EM         =   &H1f???
                        DECLARE SUB fpreset CDECL LIB "msvcrt20.dll" ALIAS "_fpreset" ()
                        DECLARE SUB control87 CDECL LIB "msvcrt20.dll" ALIAS "_control87" ( BYVAL NewVal AS DWORD, BYVAL MaskVal AS DWORD)
                        ' used this code after calling PrintDlg
                        control87 %MCW_EM, %MCW_EM
                        The PB code above eliminates the Exception generated by floating
                        point calculations after calling PrintDlg.

                        Now, I need to convert the two C calls into PB code using assembler !

                        I examined the FPU Instruction set and the only instructions that
                        would seem to accomplish what I want are :

                        FINIT (Initialize the FPU after checking error condition)
                        FNINIT (same but no error checking)

                        FCLEX (Clear Floating point exception flags after error checking)
                        FNCLEX (same but no error checking)

                        FLDCW address (Load Control Register Status)
                        FSTCW address (Store Control Register Status)

                        It would seem that the function call fpreset is likely just
                        the FNINIT instruction.

                        Since control87 uses parameters (a value and a mask), it is likely
                        multiple instructions likely using FLDCW and FSTCW !

                        This is where I need some help from an assembler expert !

                        Chris Boss
                        Computer Workshop
                        Developer of "EZGUI"


                        • #13
                          I suspect that changing the state of the FPU is likely to be similar to
                          changing CPU registers at random-- the effects won't be pretty. This is
                          not clearly safe to play with. Let me see what R&D has to say.

                          Tom Hanlin
                          PowerBASIC Staff


                          • #14
                            The following assembler instructions seem the most likely to
                            be the ones used by _control87 :

                            FLDCW address (Load Control Register Status)
                            FSTCW address (Store Control Register Status)

                            The following assembler instructions seem the most likely to
                            be the ones used by _fpreset :

                            FINIT (Initialize the FPU after checking error condition)
                            FNINIT (same but no error checking)


                            There seems to be no other way to solve this problem !
                            The printer driver is likely changing the FPU Control Word's
                            Exception Mask Flags and when PB code attempts any Floating point
                            calculations, the 10h Exception is generated (or worse).

                            As long as the FPU control word is set to something "acceptable" to
                            how PB handles Floating point calculations, there shouldn't be a
                            problem. The problem is, I don't know what PB expects as far as the
                            FPU Control Word !

                            Any suggestions from R&D would be appreciated.

                            As a side thought, Powerbasic should consider adding its own
                            versions of _fpreset and _control87 . _control87 is a very useful
                            tool for controlling how the FPU handles certain things. You can
                            set things like the precision, rounding, exception maskes, ect. with

                            All the Windows C compilers have these commands in their libraries.

                            Chris Boss
                            Computer Workshop
                            Developer of "EZGUI"


                            • #15
                              According to R&D, it is not safe to fiddle with the FPU status using
                              assembly language. Doing so could cause a variety of undesireable side-effects.

                              There is another way to resolve the problem: replace the buggy printer
                              driver. Without knowing exactly what the driver is doing wrong, there can be
                              no reliable work-around in your program anyway. Bear in mind that the printer
                              driver functions asynchronously with respect to your program.

                              I'll add a second tick to _fpreset and _control87 on the wish list.

                              Tom Hanlin
                              PowerBASIC Staff


                              • #16

                                As Ron pointed out, these functions are located in the
                                msvcrtxx.dll files. I have NT4 on my machine and the following
                                versions are listed in system32 subdirectory:


                                All these dll's have the functions in question. I would recommend
                                doing a "runtime" load of the various dll's and check for a return
                                on LoadLibrary and use the one that returns non-NULL. Then get
                                the procedure address and make the calls.




                                • #17

                                  It doesn't make much sense that most C compilers have the
                                  _control87 procedure (which does fiddle with the FPU status)
                                  if it was so dangerous.

                                  I would assume that when the operating system switches between
                                  threads, it would save the status of the FPU for each thread,
                                  otherwise the OS would be very unstable running multiple threads.

                                  Chris Boss
                                  Computer Workshop
                                  Developer of "EZGUI"


                                  • #18

                                    How about if I Save the status of the FPU from before calling
                                    the PrintDlg function and then restore it to the same values after
                                    the PrintDlg function returns ?

                                    This would seem safe to me.

                                    Chris Boss
                                    Computer Workshop
                                    Developer of "EZGUI"


                                    • #19

                                      What happens if another app access the printer driver either
                                      before or after your app does? It doesn't seem to me that you can
                                      ever be sure that the settings are correct if the printer driver
                                      can screw it up on a moments notice.....

                                      Bernard Ertl
                                      Bernard Ertl
                                      InterPlan Systems


                                      • #20
                                        Here is an interesting discussion of the very samme problem on a
                                        News group :


                                        A number of programmers "do" fiddle with the FPU state to solve
                                        problems !

                                        Likely a number apps either don't use floating point calculations
                                        so they don't exhibit this problem with print drivers. Likely others
                                        take defensive steps and they do fiddle with the FPU states after
                                        making some function calls.

                                        The HP drivers (which many end users have) seem to be the most
                                        notorious for this problem.

                                        I would appreciate any suggestions from anyone with experience
                                        dealing with this kind of problem.

                                        While the easiest solution is to simply tell people to get a new
                                        printer driver, there are likely some printers that do not have
                                        driver updates. If I can fiddle with the FPU state safely (only after the
                                        PrintDlg call) to prevent the problem (which has been demonstrated
                                        to work), this would seem a better solution to me.

                                        Are there any assembler experts out there who could write a simple
                                        (smart and as safe as possible) FPU reset function ?

                                        Chris Boss
                                        Computer Workshop
                                        Developer of "EZGUI"