Summary: | SIGFPE in _cairo_fixed_from_double | ||
---|---|---|---|
Product: | cairo | Reporter: | ellson |
Component: | general | Assignee: | Carl Worth <cworth> |
Status: | RESOLVED FIXED | QA Contact: | cairo-bugs mailing list <cairo-bugs> |
Severity: | normal | ||
Priority: | high | CC: | billy.biggs, jwatt |
Version: | 0.9.3 | ||
Hardware: | x86 (IA32) | ||
OS: | Linux (All) | ||
Whiteboard: | |||
i915 platform: | i915 features: | ||
Attachments: | Source code illustrating one case of FPE in cairo. |
Description
ellson
2005-03-08 07:15:07 UTC
I can only get that to generate an FPE if I explicitly enable FE_INVALID. Is your code is enabling this exception? #include <stdio.h> #include <stdint.h> #define _GNU_SOURCE #include <fenv.h> int main() { double d = -33750.7673118194; feenableexcept(FE_INVALID); fprintf (stderr, "foo: %d\n", (int32_t) (d * 65536)); return 0; } Ah yes, so that probably explains why I was unable to create a small test case. In dot.c (from graphviz-2.4) I set: feenableexcept( FE_DIVBYZERO | FE_OVERFLOW | FE_INVALID ) Thanks to Billy Biggs, I been able to create a small test case illustrating this bug. Please find attached. Created attachment 3233 [details] [review] xcursor-4244-reset-theme-name.diff Created attachment 3234 [details] [review] Mighty Mouse Horizontal Scrolling with inverting z axis. Unfortunately, we've lost many of the attachments to freedesktop.org bugzilla. Would you happen to have the attachments still around? I'll attach the recent "simple" test case (close, if not exactly the same as the previous attachment). Cairo seems to rely on some sort of automatic corrective behavior for FP errors (Is this behavior documented anywhere? Can it be counted on cross-platform?). If you enable all the possible FP errors there are a flood of problems. In graphviz we are FP error clean and normally keep the error reporting enabled. I finally worked out how to disable the FP error reporting just around the calls to cairo. Created attachment 2923 [details]
Source code illustrating one case of FPE in cairo.
No, Cairo isn't intentionally generating FP errors ... though it's certainly possible there are some places that it's generating FP errors in places that don't matter - the moral equivalent of: c = a / b; if (b > 0) return c; else return 0; Can you check if compiling Cairo with -ffloat-store fixes the problem - your test case seems to trigger a problem with if (m1 == m2) return 0; y_intersect = _cairo_fixed_from_double ((b2 - b1) / (m1 - m2)); Which looks like a typical 80-bit float register problem. ( I don't think your example is mathmatically correct .. but no matter. ) I've been using the cairo-0.9.2-2 shipped with Fedora, which produces FE_INVALID. Something must have changed since then because cairo from CVS produces FE_INEXACT. (I wish I knew how to detect which FP error has occurred. fetestexcept(FE_ALL_EXCEPT) always returns zero. I've been checking for any error with FP_ALL_EXCEPT, then narrowing it down by trying the specific exceptions one at a time.) Rebulding cairo with -ffloat-store made no difference. Investigated a little bit and I think it's basically a stroker problem - _cairo_pen_stroke_spline() calls _cairo_traps_tessellate_polygon() with a polygon that has two nearly parallel edges, and intersecting them causes a division by zero, or a catastrophic lack of accuracy. Looking at the polygon that gets passed in, it has, for example: (gdb) p polygon->edges[1] $5 = {edge = {p1 = {x = 818734, y = 1992760}, p2 = {x = 926867, y = 2089629}}, clockWise = 0, current_x = 818734} (gdb) p polygon->edges[2] $6 = {edge = {p1 = {x = 818734, y = 1992760}, p2 = {x = 926867, y = 2089629}}, clockWise = 0, current_x = 823407} I don't really understand the polygon structure, but that looks fishy. Anyways, would require some detailed digging to figure it out. Move bugs against "cvs" version to "0.9.3" so we can remove the "cvs" version. Seems to still happen, though in a different code path than in comment 11. Since the exception is FE_INEXACT, it sounds like the accuracy of the FP is not enough to compute the result exactly. I wonder if this has real-life consequences or not (extreme scaling could of course bring the error visible). Other than detecting the accuracy of the FP unit (can that be done?) and rounding the values to acceptable values, I'm guessing there isn't much to do here. This is a problem that needs to be specifically requested for by setting the handler anyway. Current backtrace looks like: Program received signal SIGFPE, Arithmetic exception. *INT_cairo_matrix_transform_distance (matrix=0x8053ec8, dx=0xbfeb11d8, dy=0xbfeb11d0) at cairo-matrix.c:331 331 new_x = (matrix->xx * *dx + matrix->xy * *dy); (gdb) bt #0 *INT_cairo_matrix_transform_distance (matrix=0x8053ec8, dx=0xbfeb11d8, dy=0xbfeb11d0) at cairo-matrix.c:331 #1 0xb7f3b815 in *INT_cairo_matrix_transform_point (matrix=0x8053ec8, x=0xbfeb11d8, y=0xbfeb11d0) at cairo-matrix.c:350 #2 0xb7f375ba in _cairo_gstate_user_to_backend (gstate=0x8053e10, x=0xbfeb11d8, y=0xbfeb11d0) at cairo-gstate.c:731 #3 0xb7f3134a in *INT_cairo_move_to (cr=0x8053df0, x=19.800000000000001, y=35.200000000000003) at cairo.c:1381 #4 0x080487e9 in main () We routinely now test with FPE enabled in the test-suite [since 1.6], although only for the fatal traps DivideByZero, Overflow and Invalid. Underflow and Inexac,t I consider to be mere warnings that the floating point arithmetic can no longer represent the result without loss of accuracy. If you consider the application of such values within cairo (e.g. conversion to 24.8 fixed point during rasteristation, or printing using %.18f to vector targets) then those two exceptions are of no significant consequence (one hopes). Wrt the original bug, cairo_polygon_t now discards degenerate edges and so the division-by-zero is prevented at source. So given the specific bug has been fixed and the general bug has been incorporated into routine testing, I feel confident in closing this bug. Many thanks for the original report. |
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.