Bug 9906

Summary: evolution crash to _cairo_gstate_backend_to_user()
Product: cairo Reporter: Sebastien Bacher <seb128>
Component: generalAssignee: Carl Worth <cworth>
Status: RESOLVED FIXED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: blocker    
Priority: medium    
Version: 1.3.13   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:

Description Sebastien Bacher 2007-02-07 12:32:45 UTC
That bug has been opened on https://launchpad.net/bugs/83744

"Binary package hint: evolution

When I select to print a message, Evolution crashes. I just can see the printing dialog to appear.
...
"

Debug backtrace for the crash:

711         cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y);
(gdb) bt full
#0  0xb75e53bd in _cairo_gstate_backend_to_user (gstate=0x0, x=0xbfc9e508, y=0xbfc9e500)
    at /build/buildd/libcairo-1.3.12/src/cairo-gstate.c:711
No locals.
#1  0xb75ddd38 in *INT_cairo_get_current_point (cr=0x87c7dc0, x_ret=0x85238b8, y_ret=0x85238c0)
    at /build/buildd/libcairo-1.3.12/src/cairo.c:2828
        status = <value optimized out>
        x_fixed = 31928960
        y_fixed = 52340096
        x = 487.197265625
        y = 798.646484375
#2  0xb7684dab in _pango_cairo_do_glyph_string (cr=0x87c7dc0, font=0x85d2348, glyphs=0x8885120, do_path=0)
    at /build/buildd/pango1.0-1.15.5/./pango/pangocairo-render.c:482
        free_renderer = <value optimized out>
        crenderer = (PangoCairoRenderer *) 0x8523890
#3  0xb74cc060 in draw_glyphs (painter=0x88021f0, x=5648, y=11280, item=0x879b8a0, glyphs=0x8885120, fg=0x0, bg=0x0)
    at htmlprinter.c:632
        printer = (HTMLPrinter *) 0x88021f0
        print_x = 23.515625
        print_y = 11.015625
        log_rect = {x = 0, y = -11264, width = 439296, height = 14336}
        properties = {underline = 0, strikethrough = 0, fg_color = 0xb1e5663c, bg_color = 0x0}
        cr = (cairo_t *) 0x87c7dc0
#4  0xb74c9229 in html_painter_draw_glyphs (painter=0x88021f0, x=5648, y=11280, item=0x879b8a0, glyphs=0x8885120, fg=0x0, 
    bg=0x0) at htmlpainter.c:637
No locals.
#5  0xb74e0b2d in draw (o=0x87b6d00, p=0x88021f0, x=-528, y=5104, width=525594, height=799744, tx=5648, ty=16)
    at htmltextslave.c:789
        owner = (HTMLText *) 0xb1e4d8a0
        paint = {x = 0, y = 5104, width = 439296, height = 9232}
#6  0xb74c4172 in html_object_draw (o=0x87b6d00, p=0x88021f0, x=-528, y=5104, width=525594, height=799744, tx=5648, ty=16)
    at htmlobject.c:1042
No locals.
#7  0xb74911b6 in draw (o=0xb1e4d7c8, p=0x88021f0, x=-528, y=1473520, width=525594, height=799744, tx=5648, ty=-1468400)
    at htmlclue.c:268
        obj = (HTMLObject *) 0x87b6d00
#8  0xb74950f1 in draw (self=0xb1e4d7c8, painter=0x88021f0, x=-528, y=1473520, width=525594, height=799744, tx=5648, 
    ty=-1468400) at htmlclueflow.c:1371
No locals.
#9  0xb74c4172 in html_object_draw (o=0xb1e4d7c8, p=0x88021f0, x=-528, y=1473520, width=525594, height=799744, tx=5648, 
    ty=-1468400) at htmlobject.c:1042
No locals.
#10 0xb74911b6 in draw (o=0xb1e41300, p=0x88021f0, x=-528, y=1473520, width=525594, height=799744, tx=5648, ty=-1468400)
    at htmlclue.c:268
        obj = (HTMLObject *) 0xb1e4d7c8
...

from gdb on the frame 1:

(gdb) p *cr
$1 = {ref_count = 1, status = CAIRO_STATUS_INVALID_RESTORE, path = {op_buf_head = 0x886f9f0, op_buf_tail = 0x886f9f0, 
    arg_buf_head = 0x888e598, arg_buf_tail = 0x888e598, last_move_point = {x = 31928960, y = 52340096}, current_point = {
      x = 31928960, y = 52340096}, has_current_point = 1, has_curve_to = 0}, gstate = 0x0}
Comment 1 Carl Worth 2007-02-15 16:55:47 UTC
(In reply to comment #0)
> (gdb) p *cr
> $1 = {ref_count = 1, status = CAIRO_STATUS_INVALID_RESTORE, path = {op_buf_head
> = 0x886f9f0, op_buf_tail = 0x886f9f0, 
>     arg_buf_head = 0x888e598, arg_buf_tail = 0x888e598, last_move_point = {x =
> 31928960, y = 52340096}, current_point = {
>       x = 31928960, y = 52340096}, has_current_point = 1, has_curve_to = 0},
> gstate = 0x0}

This part is very interesting. If you've hit an INVALID_RESTORE case then cairo_t should shut down and you shouldn't be able to get it to do anything after that anymore, (and especially not crash).

Could you break on _cairo_error which should show you where the INVALID_RESTORE is first happening, and then step through to see how you're getting from there to the crash?

Thanks,

-Carl
Comment 2 Carl Worth 2007-03-02 03:53:59 UTC
(In reply to comment #1)
> Could you break on _cairo_error which should show you where the INVALID_RESTORE
> is first happening, and then step through to see how you're getting from there
> to the crash?

Oh, never mind. It's clear enough from the existing backtrace already. Any INVALID_RESTORE condition was leaving a NULL gstate and almost any cairo_get_* call would dererference that and trigger the crash.

I augmented cairo's test suite to exercise the crash, then I fixed the bug.

You can see the commit I just pushed out here:

http://gitweb.freedesktop.org/?p=cairo;a=commitdiff;h=6da7f140334835be9a972db75de78d99b8bd24b1

This is currently available in cairo 1.3.15 as made available in git, and will be pushed out very shortly in the cairo 1.4 release.

Meanwhile, there's still a bug in evolution somewhere that's leading to the INVALID_RESTORE in the first place, (that is, calling cairo_restore without a matching call to cairo_save). This fix will prevent the crash, and will instead replace it with cairo simply refusing to draw anything after the invalid restore state. So you'll still want to fix that.

-Carl
Comment 3 Sebastien Bacher 2007-03-02 06:42:39 UTC
Thank you for fixing the bug Carl. I didn't update the bug with the informations you asked for because the Ubuntu bug submitter didn't reply to that question, he updated the bug to say it works fine for him now though which means the evolution hackers probably also fixed their part of the bug

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.