Browse Source

* reset exception flags, resolves #37468 on x86_64

git-svn-id: trunk@45995 -
florian 5 years ago
parent
commit
eac6675cba
4 changed files with 43 additions and 9 deletions
  1. 1 0
      .gitattributes
  2. 8 9
      rtl/linux/i386/sighnd.inc
  3. 10 0
      rtl/linux/x86_64/sighnd.inc
  4. 24 0
      tests/webtbs/tw37468.pp

+ 1 - 0
.gitattributes

@@ -18400,6 +18400,7 @@ tests/webtbs/tw37400.pp svneol=native#text/pascal
 tests/webtbs/tw3742.pp svneol=native#text/plain
 tests/webtbs/tw3742.pp svneol=native#text/plain
 tests/webtbs/tw37427.pp svneol=native#text/pascal
 tests/webtbs/tw37427.pp svneol=native#text/pascal
 tests/webtbs/tw37449.pp svneol=native#text/pascal
 tests/webtbs/tw37449.pp svneol=native#text/pascal
+tests/webtbs/tw37468.pp svneol=native#text/pascal
 tests/webtbs/tw3751.pp svneol=native#text/plain
 tests/webtbs/tw3751.pp svneol=native#text/plain
 tests/webtbs/tw3758.pp svneol=native#text/plain
 tests/webtbs/tw3758.pp svneol=native#text/plain
 tests/webtbs/tw3764.pp svneol=native#text/plain
 tests/webtbs/tw3764.pp svneol=native#text/plain

+ 8 - 9
rtl/linux/i386/sighnd.inc

@@ -76,17 +76,16 @@ begin
                           res:=207;  {'Coprocessor Error'}
                           res:=207;  {'Coprocessor Error'}
                       end;
                       end;
                   end;
                   end;
-                with ucontext^.uc_mcontext.fpstate^ do
-                  begin
-                    { Reset Status word }
-                    sw:=sw and not FPU_ExceptionMask;
-                    { Restoree default control word }
-                    cw:=Default8087CW;
-                    { Reset Tag word to $ffff for all empty }
-                    tag:=$ffff;
-                  end;
                end;
                end;
           end;
           end;
+        if assigned(ucontext^.uc_mcontext.fpstate) then
+          with ucontext^.uc_mcontext.fpstate^ do
+            begin
+              { Reset Status word }
+              sw:=sw and not(FPU_ExceptionMask);
+              mxcsr:=mxcsr and not(MM_ExceptionMask);
+              SysResetFPU;
+            end;
       end;
       end;
     SIGBUS:
     SIGBUS:
       res:=214;
       res:=214;

+ 10 - 0
rtl/linux/x86_64/sighnd.inc

@@ -81,6 +81,11 @@ procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigCon
                     res:=207
                     res:=207
                   else
                   else
                     res:=207;  {'Coprocessor Error'}
                     res:=207;  {'Coprocessor Error'}
+
+                  { exceptions are handled, clear all flags
+                    as we return from SignalToRunerrer, we have to clear the exception flags in the context }
+                  if assigned(SigContext^.fpstate) then
+                    SigContext^.fpstate^.swd:=SigContext^.fpstate^.swd and not(FPU_All);
                 end;
                 end;
                 MMState:=getMMState(SigContext^);
                 MMState:=getMMState(SigContext^);
                 if (MMState and MM_ExceptionMask)<>0 then
                 if (MMState and MM_ExceptionMask)<>0 then
@@ -98,6 +103,11 @@ procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigCon
                       res:=216
                       res:=216
                     else
                     else
                       res:=207;  {'Coprocessor Error'}
                       res:=207;  {'Coprocessor Error'}
+
+                    { exceptions are handled, clear all flags
+                      as we return from SignalToRunerrer, we have to clear the exception flags in the context }
+                    if assigned(SigContext^.fpstate) then
+                      SigContext^.fpstate^.mxcsr:=SigContext^.fpstate^.mxcsr and not(MM_ExceptionMask);
                   end;
                   end;
             end;
             end;
           SysResetFPU;
           SysResetFPU;

+ 24 - 0
tests/webtbs/tw37468.pp

@@ -0,0 +1,24 @@
+program Project1;
+
+{$mode objfpc}{$H+}
+
+uses
+  math, sysutils;
+var
+  a,b: double;
+begin
+  a := 0;
+  b := -3;
+  try
+    try
+      writeln(power(a,b));
+    except
+      on e: EDivByZero do begin
+        writeln(Infinity);
+      end;
+    end;
+  except
+    halt(1);
+  end;
+  writeln('ok');
+end.