Avalonia 中使用 CEF 在 Ubuntu 运行崩溃分析

在 Linux 上使用 Avalonia 和 CefGlue:崩溃分析

介绍

本文主要记录了在 Avalonia 中使用 CefGlue(基于 .NET 的 Chrome 嵌入内核的封装库)时遇到的问题,目的是测试 Avalonia 的 Chrome 内核在 Linux 系统中的兼容性。然而在实际运行时,我们意外地遇到了运行崩溃的问题。


环境

测试环境如下:

  • Ubuntu 24.04 桌面环境:GNOME
  • KUbuntu 24.04 桌面环境:KDE
  • Avalonia 版本:11.0.4 ~ 11.2.2

测试示例

测试用例来源于 CefGlue GitHub 仓库 中的 Demo.Avalonia 示例项目。


测试结果

  1. Ubuntu 22.10
    无法运行,提示不兼容并要求更高版本的依赖。

  2. Ubuntu 24.04
    同样无法运行,出现运行时崩溃。

  3. KUbuntu 24.04
    运行正常。


问题原因

问题发生在加载 CefBrowser 时。调试表明这是由于未正确初始化字体的 Face,导致文本整形过程中出现崩溃。


解决方案(临时修复)

如果在运行时遇到以下 Segment Fault 错误,可以通过提前初始化一次文本整形来规避问题。

修复代码

在应用的启动代码中添加以下方法:

public partial class App : Application
{
    public override void OnFrameworkInitializationCompleted()
    {
        Preinitialize_ShapeText();  // 提前初始化字体的 ShapeText

        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            // 应用生命周期初始化代码
        }

        base.OnFrameworkInitializationCompleted();
    }

    private static void Preinitialize_ShapeText()
    {
        var text = "FixedShapeTextCrashBug\t";
        var options = new TextShaperOptions(
            Typeface.Default.GlyphTypeface,
            12, 0,
            CultureInfo.CurrentCulture,
            100);
        var shapedBuffer = TextShaper.Current.ShapeText(
            text.AsMemory().Slice(6), options);
    }
}

错误详情

运行时的异常结果如下:

Thread 1 "Xilium.CefGlue." received signal SIGSEGV, Segmentation fault.
0x0000555555dadea0 in ?? ()
(gdb) bt
#0  0x0000555555dadea0 in ?? ()
#1  0x00007fff746f8aab in hb_face_t::reference_table (tag=<optimized out>, this=<optimized out>)
    at ../src/hb-face.hh:79
...

问题发生在 Harfbuzz 的 hb_face_t::reference_table 函数调用过程中,具体分析详见下文。


分析过程

初步排查

  1. 检查 Harfbuzz 库版本
    怀疑 Harfbuzz 库版本不匹配,但 Ubuntu 和 Kubuntu 系统中使用的是相同版本。

  2. 升级 Avalonia
    将 Avalonia 从 11.0.4 升级至 11.2.2,但问题依旧。

  3. 检查 Avalonia 的 Skia 更新
    Avalonia 的 GitHub 仓库最近更新了 Skia 和 Harfbuzz 到版本 8.3.3。尝试升级 Avalonia 到 Nightly 版本,问题依然存在。

调试堆栈

托管堆栈的错误信息:

(lldb) clrstack
OS Thread Id: 0x84ef (1)
        Child SP               IP Call Site
00007FFFFFFF60D8 0000555556a9a410 [InlinedCallFrame: 00007fffffff60d8] HarfBuzzSharp.HarfBuzzApi.hb_shape_full(IntPtr, IntPtr, HarfBuzzSharp.Feature*, UInt32, Void**)
00007FFFFFFF60D8 00007fff7aea7023 [InlinedCallFrame: 00007fffffff60d8] HarfBuzzSharp.HarfBuzzApi.hb_shape_full(IntPtr, IntPtr, HarfBuzzSharp.Feature*, UInt32, Void**)
00007FFFFFFF60D0 00007FFF7AEA7023 ILStubClass.IL_STUB_PInvoke(IntPtr, IntPtr, HarfBuzzSharp.Feature*, UInt32, Void**)
00007FFFFFFF6160 00007FFF7AEA6BE6 HarfBuzzSharp.Font.Shape(HarfBuzzSharp.Buffer, System.Collections.Generic.IReadOnlyList`1<HarfBuzzSharp.Feature>, System.Collections.Generic.IReadOnlyList`1<System.String>)
00007FFFFFFF6310 00007FFF7AEA657A HarfBuzzSharp.Font.Shape(HarfBuzzSharp.Buffer, HarfBuzzSharp.Feature[])
00007FFFFFFF6340 00007FFF7AEA44C4 Avalonia.Skia.TextShaperImpl.ShapeText(System.ReadOnlyMemory`1<Char>, Avalonia.Media.TextFormatting.TextShaperOptions) [E:\Exploit\AvaloniaUI\Avalonia\src\Skia\Avalonia.Skia\TextShaperImpl.cs @ 46]
00007FFFFFFF66B0 00007FFF7AEA3F8B Avalonia.Media.TextFormatting.TextShaper.ShapeText(System.ReadOnlyMemory`1<Char>, Avalonia.Media.TextFormatting.TextShaperOptions) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Media\TextFormatting\TextShaper.cs @ 45]
00007FFFFFFF6720 00007FFF7AEA3D6D Avalonia.Media.TextFormatting.TextFormatterImpl.ShapeTogether(System.Collections.Generic.IReadOnlyList`1<Avalonia.Media.TextFormatting.UnshapedTextRun>, System.ReadOnlyMemory`1<Char>, Avalonia.Media.TextFormatting.TextShaperOptions, Avalonia.Media.TextFormatting.TextShaper, RentedList`1<Avalonia.Media.TextFormatting.TextRun>) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Media\TextFormatting\TextFormatterImpl.cs @ 372]
00007FFFFFFF6820 00007FFF7AE9599E Avalonia.Media.TextFormatting.TextFormatterImpl.ShapeTextRuns(System.Collections.Generic.IReadOnlyList`1<Avalonia.Media.TextFormatting.TextRun>, Avalonia.Media.TextFormatting.TextParagraphProperties, Avalonia.Media.TextFormatting.FormattingObjectPool, Avalonia.Media.FontManager, Avalonia.Media.FlowDirection ByRef) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Media\TextFormatting\TextFormatterImpl.cs @ 279]
00007FFFFFFF6C20 00007FFF7AE90D5A Avalonia.Media.TextFormatting.TextFormatterImpl.FormatLine(Avalonia.Media.TextFormatting.ITextSource, Int32, Double, Avalonia.Media.TextFormatting.TextParagraphProperties, Avalonia.Media.TextFormatting.TextLineBreak) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Media\TextFormatting\TextFormatterImpl.cs @ 49]
00007FFFFFFF6DB0 00007FFF7AE8F816 Avalonia.Media.TextFormatting.TextLayout.CreateTextLines() [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Media\TextFormatting\TextLayout.cs @ 578]
00007FFFFFFF71F0 00007FFF7AE8F3B9 Avalonia.Media.TextFormatting.TextLayout..ctor(Avalonia.Media.TextFormatting.ITextSource, Avalonia.Media.TextFormatting.TextParagraphProperties, Avalonia.Media.TextTrimming, Double, Double, Int32) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Media\TextFormatting\TextLayout.cs @ 144]
00007FFFFFFF7270 00007FFF7AE8DB3B Avalonia.Controls.TextBlock.CreateTextLayout(System.String) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\TextBlock.cs @ 673]
00007FFFFFFF7410 00007FFF7AE8D444 Avalonia.Controls.Primitives.AccessText.CreateTextLayout(System.String) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Primitives\AccessText.cs @ 87]
00007FFFFFFF7450 00007FFF7AE8D32B Avalonia.Controls.TextBlock.get_TextLayout() [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\TextBlock.cs @ 191]
00007FFFFFFF74A0 00007FFF7AE8D045 Avalonia.Controls.TextBlock.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\TextBlock.cs @ 732]
00007FFFFFFF76C0 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFF7970 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFF7B80 00007FFF7AE7C16D Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\LayoutHelper.cs @ 47]
00007FFFFFFF7D20 00007FFF7AE7DAA3 Avalonia.Controls.Presenters.ContentPresenter.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Presenters\ContentPresenter.cs @ 601]
00007FFFFFFF7E00 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFF80B0 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFF82C0 00007FFF7AE7AA5D Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 613]
00007FFFFFFF83C0 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFF8670 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFF8880 00007FFF7AE87ACD Avalonia.Controls.StackPanel.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\StackPanel.cs @ 272]
00007FFFFFFF8B30 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFF8DE0 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFF8FF0 00007FFF7AE876B7 Avalonia.Controls.Grid.MeasureCell(Int32, Boolean) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Grid.cs @ 1138]
00007FFFFFFF90F0 00007FFF7AE84C0B Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean, Boolean ByRef) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Grid.cs @ 997]
00007FFFFFFF9470 00007FFF7AE84A80 Avalonia.Controls.Grid.MeasureCellsGroup(Int32, Avalonia.Size, Boolean, Boolean) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Grid.cs @ 960]
00007FFFFFFF94B0 00007FFF7AE810B1 Avalonia.Controls.Grid.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Grid.cs @ 448]
00007FFFFFFF97D0 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFF9A80 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFF9C90 00007FFF7AE7C16D Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\LayoutHelper.cs @ 47]
00007FFFFFFF9E30 00007FFF7AE7DAA3 Avalonia.Controls.Presenters.ContentPresenter.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Presenters\ContentPresenter.cs @ 601]
00007FFFFFFF9F10 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFFA1C0 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFFA3D0 00007FFF7AE7AA5D Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 613]
00007FFFFFFFA4D0 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFFA780 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFFA990 00007FFF7AE7C16D Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness, Avalonia.Thickness) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\LayoutHelper.cs @ 47]
00007FFFFFFFAB30 00007FFF7AE7DAA3 Avalonia.Controls.Presenters.ContentPresenter.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Presenters\ContentPresenter.cs @ 601]
00007FFFFFFFAC10 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFFAEC0 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFFB0D0 00007FFF7AE7CEE8 Avalonia.Layout.LayoutHelper.MeasureChild(Avalonia.Layout.Layoutable, Avalonia.Size, Avalonia.Thickness) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\LayoutHelper.cs @ 63]
00007FFFFFFFB1E0 00007FFF7AE7CD6F Avalonia.Controls.Decorator.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Decorator.cs @ 54]
00007FFFFFFFB280 00007FFF7AE7CCA6 Avalonia.Controls.Primitives.VisualLayerManager.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Primitives\VisualLayerManager.cs @ 157]
00007FFFFFFFB2F0 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFFB5A0 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFFB7B0 00007FFF7AE7AA5D Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 613]
00007FFFFFFFB8B0 00007FFF7AE7ADC9 Avalonia.Layout.Layoutable.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 549]
00007FFFFFFFBB60 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFFBD70 00007FFF7AE7AA5D Avalonia.Layout.Layoutable.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 613]
00007FFFFFFFBE70 00007FFF7AE79CB8 Avalonia.Controls.Window.MeasureOverride(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Window.cs @ 1077]
00007FFFFFFFC0E0 00007FFF7AC4F829 Avalonia.Controls.WindowBase.MeasureCore(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\WindowBase.cs @ 289]
00007FFFFFFFC150 00007FFF7AC4F3BE Avalonia.Layout.Layoutable.Measure(Avalonia.Size) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\Layoutable.cs @ 378]
00007FFFFFFFC360 00007FFF7AC4EFB8 Avalonia.Layout.LayoutManager.Measure(Avalonia.Layout.Layoutable) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\LayoutManager.cs @ 304]
00007FFFFFFFC450 00007FFF7AC4ED68 Avalonia.Layout.LayoutManager.ExecuteInitialLayoutPass() [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Base\Layout\LayoutManager.cs @ 191]
00007FFFFFFFC480 00007FFF7AC475FE Avalonia.Controls.Window.ShowCore[[System.__Canon, System.Private.CoreLib]](Avalonia.Controls.Window, Boolean) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Window.cs @ 750]
00007FFFFFFFC9F0 00007FFF7AC46F8B Avalonia.Controls.Window.Show() [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\Window.cs @ 631]
00007FFFFFFFCA10 00007FFF7AC46EEC Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.ShowMainWindow() [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\ApplicationLifetimes\ClassicDesktopStyleApplicationLifetime.cs @ 151]
00007FFFFFFFCA40 00007FFF7AC46B37 Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.StartCore(System.String[]) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\ApplicationLifetimes\ClassicDesktopStyleApplicationLifetime.cs @ 141]
00007FFFFFFFCA80 00007FFF7AC46A94 Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(System.String[]) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\ApplicationLifetimes\ClassicDesktopStyleApplicationLifetime.cs @ 120]
00007FFFFFFFCAB0 00007FFF78E2395C Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(Avalonia.AppBuilder, System.String[], System.Action`1<Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime>) [E:\Exploit\AvaloniaUI\Avalonia\src\Avalonia.Controls\ApplicationLifetimes\ClassicDesktopStyleApplicationLifetime.cs @ 277]
00007FFFFFFFCB00 00007FFF78E2195C CefGlueApp.Desktop.Program.Main(System.String[]) [E:\Exploit\AvaloniaUI\Avalonia\samples\CefGlueApp.Desktop\Program.cs @ 13]

非托管堆栈的错误信息:

Thread 1 "Xilium.CefGlue." received signal SIGSEGV, Segmentation fault.
0x0000555555dadea0 in ?? ()
(gdb) bt
#0  0x0000555555dadea0 in ?? ()
#1  0x00007fff746f8aab in hb_face_t::reference_table (tag=<optimized out>, this=<optimized out>)
    at ../src/hb-face.hh:79
#2  hb_face_reference_table (face=<optimized out>, tag=<optimized out>) at ../src/hb-face.cc:411
#3  0x00007fff7474b3ab in hb_sanitize_context_t::reference_table<OT::Layout::GSUB> (
    tableTag=1196643650, face=0x555555daffd0, this=0x7fffffff7420) at ../src/hb-sanitize.hh:500
#4  OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::accelerator_t (this=<optimized out>,
    face=<optimized out>, this=<optimized out>, face=<optimized out>)
    at ../src/OT/Layout/GPOS/../../../hb-ot-layout-gsubgpos.hh:4757
#5  0x00007fff7473cce3 in OT::GSUB_accelerator_t::GSUB_accelerator_t (face=0x555555daffd0,
    this=0x555555e52cc0) at ../src/OT/Layout/GSUB/GSUB.hh:55
--Type <RET> for more, q to quit, c to continue without paging--
#6  hb_lazy_loader_t<OT::GSUB_accelerator_t, hb_face_lazy_loader_t<OT::GSUB_accelerator_t, 25u>, hb_face_t, 25u, OT::GSUB_accelerator_t>::create (data=<optimized out>) at ../src/hb-machinery.hh:258
#7  hb_data_wrapper_t<hb_face_t, 25u>::call_create<OT::GSUB_accelerator_t, hb_face_lazy_loader_t<OT::GSUB_accelerator_t, 25u> > (this=<optimized out>) at ../src/hb-machinery.hh:158
#8  hb_lazy_loader_t<OT::GSUB_accelerator_t, hb_face_lazy_loader_t<OT::GSUB_accelerator_t, 25u>, hb_face_t, 25u, OT::GSUB_accelerator_t>::get_stored (this=<optimized out>) at ../src/hb-machinery.hh:221
#9  hb_lazy_loader_t<OT::GSUB_accelerator_t, hb_face_lazy_loader_t<OT::GSUB_accelerator_t, 25u>, hb_face_t, 25u, OT::GSUB_accelerator_t>::get (this=<optimized out>) at ../src/hb-machinery.hh:245
#10 hb_lazy_loader_t<OT::GSUB_accelerator_t, hb_face_lazy_loader_t<OT::GSUB_accelerator_t, 25u>, hb_face_t, 25u, OT::GSUB_accelerator_t>::operator-> (this=<optimized out>) at ../src/hb-machinery.hh:205
#11 get_gsubgpos_table (face=0x555555db8d30, table_tag=<optimized out>) at ../src/hb-ot-layout.cc:421
#12 0x00007fff7473e483 in hb_ot_layout_table_find_feature_variations (face=<optimized out>, table_tag=<optimized out>,
    coords=0x0, num_coords=0, variations_index=0x7fffffff75fc) at ../src/hb-ot-layout.cc:1445
#13 0x00007fff74781a10 in hb_ot_shape_plan_key_t::init (num_coords=0, coords=0x0, face=0x555555db8d30,
    this=0x7fffffff75fc) at ../src/hb-ot-shape.hh:45
#14 hb_shape_plan_key_t::init (this=0x7fffffff75d0, copy=<optimized out>, face=0x555555db8d30, props=<optimized out>,
    user_features=<optimized out>, num_user_features=0, coords=0x0, num_coords=0, shaper_list=0x0)
    at ../src/hb-shape-plan.cc:92
#15 0x00007fff7478b728 in hb_shape_plan_create_cached2 (face=0x555555db8d30, props=0x555555e7a2c0, user_features=0x0,
    num_user_features=0, coords=0x0, num_coords=0, shaper_list=0x0) at ../src/hb-shape-plan.cc:536
#16 0x00007fff74250627 in hb_shape_full ()
   from /home/jins/cef_tests/CefGlue/CefGlue.Demo.Avalonia/bin/Debug/net8.0/linux-x64/libHarfBuzzSharp.so
...

问题源头

根据 Harfbuzz 的源码分析,reference_table_funchb_face_t 对象中的一个回调,用于获取字体表的引用。在回调过程中,由于某些未初始化的指针导致访问无效内存,触发了段错误。

相关代码片段如下:

hb_blob_t *hb_face_t::reference_table(hb_tag_t tag) const
{
    if (unlikely(!reference_table_func))
        return hb_blob_get_empty();

    hb_blob_t *blob = reference_table_func(/*...*/, user_data);
    if (unlikely(!blob))
        return hb_blob_get_empty();

    return blob;
}

分析表明,在首次调用 ShapeText 时程序崩溃,而如果在加载 CefBrowser 前预先调用一次 ShapeText,问题可以避免。


调用链总结

完整的调用链如下:

  1. ShapeText
  2. Font.Shape
  3. hb_shape_full
  4. 调用 Harfbuzz API 进行字体表查询
  5. 触发崩溃

需要注意的是,该问题只在使用 CefBrowser 时出现,未使用 CefBrowser 的情况下运行正常。


最终解决方案

为避免崩溃,在加载 CefBrowser 之前执行一次文本整形的预初始化。这种方法虽然是临时解决方案,但可以保证程序在不同 Linux 桌面环境下的正常运行。


===
CC BY-NC-SA 4.0 知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 0xJins包含此链接),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

posted @   JinsYang  阅读(59)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示