servo / pathfinder

A fast, practical GPU rasterizer for fonts and vector graphics
Apache License 2.0
3.61k stars 204 forks source link

Infinite loop in `clip_line_segment_to_rect` #436

Open nathansobo opened 4 years ago

nathansobo commented 4 years ago

After attempting to update to fed372229a4e4730b476be6436087d06f4f2ce0f in my app, I'm seeing it hang periodically. When I sample the process, I see many of the threads occupied with stacks that look like this:

    2002 Thread_23062470
    + 2002 thread_start  (in libsystem_pthread.dylib) + 15  [0x7fff673c9b8b]
    +   2002 _pthread_start  (in libsystem_pthread.dylib) + 148  [0x7fff673ce109]
    +     2002 std::sys::unix::thread::Thread::new::thread_start::h545d31fdf79b3d9e  (in zed) + 45  [0x103db4d7d]
    +       2002 core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::he862cdbfb89d729f  (in zed) + 97  [0x103d7c831]
    +         2002 std::sys_common::backtrace::__rust_begin_short_backtrace::h676446a1390a22cc  (in zed) + 34  [0x103d7ba52]
    +           2002 rayon_core::registry::ThreadBuilder::run::h00c30b6f2120b0c7  (in zed) + 1422  [0x103d7a09e]
    +             2002 rayon_core::registry::WorkerThread::wait_until_cold::ha551cfa030ef9fe4  (in zed) + 350  [0x103df592e]
    +               2002 _$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$::execute::h86e993ae71b3f169  (in zed) + 151  [0x103bd8ee7]
    +                 2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                   2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 386  [0x103bb4d12]
    +                     2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                       2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 574  [0x103bb4dce]
    +                         2002 rayon_core::registry::WorkerThread::wait_until_cold::h12d90f5e31262005  (in zed) + 180  [0x103de83a4]
    +                           2002 rayon_core::registry::WorkerThread::execute::h56c2fd0e6ec4b97a  (in zed) + 14  [0x103d7b15e]
    +                             2002 _$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$::execute::h86e993ae71b3f169  (in zed) + 151  [0x103bd8ee7]
    +                               2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                                 2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 481  [0x103bb4d71]
    +                                   2002 rayon_core::job::StackJob$LT$L$C$F$C$R$GT$::run_inline::h100733435229296f  (in zed) + 154  [0x103bd116a]
    +                                     2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                                       2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 574  [0x103bb4dce]
    +                                         2002 rayon_core::registry::WorkerThread::wait_until_cold::h12d90f5e31262005  (in zed) + 180  [0x103de83a4]
    +                                           2002 rayon_core::registry::WorkerThread::execute::h56c2fd0e6ec4b97a  (in zed) + 14  [0x103d7b15e]
    +                                             2002 _$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$::execute::h86e993ae71b3f169  (in zed) + 151  [0x103bd8ee7]
    +                                               2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                                                 2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 386  [0x103bb4d12]
    +                                                   2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                                                     2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 386  [0x103bb4d12]
    +                                                       2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                                                         2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 574  [0x103bb4dce]
    +                                                           2002 rayon_core::registry::WorkerThread::wait_until_cold::h12d90f5e31262005  (in zed) + 180  [0x103de83a4]
    +                                                             2002 rayon_core::registry::WorkerThread::execute::h56c2fd0e6ec4b97a  (in zed) + 14  [0x103d7b15e]
    +                                                               2002 _$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$::execute::h86e993ae71b3f169  (in zed) + 151  [0x103bd8ee7]
    +                                                                 2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 458  [0x103c05bba]
    +                                                                   2002 rayon_core::registry::in_worker::hd6b8274e541998e2  (in zed) + 574  [0x103bb4dce]
    +                                                                     2002 rayon_core::registry::WorkerThread::wait_until_cold::h12d90f5e31262005  (in zed) + 180  [0x103de83a4]
    +                                                                       2002 rayon_core::registry::WorkerThread::execute::h56c2fd0e6ec4b97a  (in zed) + 14  [0x103d7b15e]
    +                                                                         2002 _$LT$rayon_core..job..StackJob$LT$L$C$F$C$R$GT$$u20$as$u20$rayon_core..job..Job$GT$::execute::h86e993ae71b3f169  (in zed) + 151  [0x103bd8ee7]
    +                                                                           2002 rayon::iter::plumbing::bridge_producer_consumer::helper::h8ddb1da964800b3e  (in zed) + 194  [0x103c05ab2]
    +                                                                             2002 rayon::iter::plumbing::Folder::consume_iter::h6e1d4b04190ded33  (in zed) + 234  [0x103bf031a]
    +                                                                               2002 pathfinder_renderer::builder::SceneBuilder::build_draw_path_on_cpu::h207de4f6e27a1440  (in zed) + 638  [0x103d6864e]
    +                                                                                 2002 pathfinder_renderer::tiler::Tiler::generate_tiles::hee32a8a548039fc5  (in zed) + 606  [0x103d6550e]
    +                                                                                   2002 pathfinder_renderer::tiler::process_segment::hba1584190896e69b  (in zed) + 125  [0x103d6594d]
    +                                                                                     2002 pathfinder_content::clip::clip_line_segment_to_rect::h12c22efb161b7557  (in zed) + 289,233,...  [0x103d83d21,0x103d83ce9,...]

Could this be related to https://github.com/servo/pathfinder/pull/419?

colorhook commented 4 years ago

There is a bug in clip_line_segment_to_rect method which in content/src/clip.rs file:

...
else if outcode.contains(Outcode::TOP) {
            point = vec2f(lerp(line_segment.from_x(),
                               line_segment.to_x(),
                               (line_segment.min_y() - line_segment.from_y()) /
                                (line_segment.max_y() - line_segment.min_y())),
                          rect.min_y());
        } else if outcode.contains(Outcode::LEFT) {
            point = vec2f(lerp(line_segment.from_x(),
                               line_segment.to_x(),
                               (line_segment.max_y() - line_segment.from_y()) /
                                (line_segment.max_y() - line_segment.min_y())),
                          rect.min_y());
        }
...

should change to

...
} else if outcode.contains(Outcode::TOP) {
            point = vec2f(lerp(line_segment.from_x(),
                               line_segment.to_x(),
                               (line_segment.min_y() - line_segment.from_y()) /
                                (line_segment.max_y() - line_segment.min_y())),
                          rect.min_y());
        } else if outcode.contains(Outcode::BOTTOM) {
            point = vec2f(lerp(line_segment.from_x(),
                               line_segment.to_x(),
                               (line_segment.max_y() - line_segment.from_y()) /
                                (line_segment.max_y() - line_segment.min_y())),
                          rect.max_y());
        }