在 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
示例项目。
测试结果
-
Ubuntu 22.10
无法运行,提示不兼容并要求更高版本的依赖。 -
Ubuntu 24.04
同样无法运行,出现运行时崩溃。 -
KUbuntu 24.04
运行正常。
问题原因
问题发生在加载 CefBrowser
时。调试表明这是由于未正确初始化字体的 Face,导致文本整形过程中出现崩溃。
解决方案(临时修复)
如果在运行时遇到以下 Segment Fault 错误,可以通过提前初始化一次文本整形来规避问题。
修复代码
在应用的启动代码中添加以下方法:
public partial class App : Application
{public override void OnFrameworkInitializationCompleted(){Preinitialize_ShapeText(); // 提前初始化字体的 ShapeTextif (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
函数调用过程中,具体分析详见下文。
分析过程
初步排查
-
检查 Harfbuzz 库版本
怀疑 Harfbuzz 库版本不匹配,但 Ubuntu 和 Kubuntu 系统中使用的是相同版本。 -
升级 Avalonia
将 Avalonia 从 11.0.4 升级至 11.2.2,但问题依旧。 -
检查 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_func
是 hb_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
,问题可以避免。
调用链总结
完整的调用链如下:
ShapeText
Font.Shape
hb_shape_full
- 调用 Harfbuzz API 进行字体表查询
- 触发崩溃
需要注意的是,该问题只在使用 CefBrowser
时出现,未使用 CefBrowser
的情况下运行正常。
最终解决方案
为避免崩溃,在加载 CefBrowser
之前执行一次文本整形的预初始化。这种方法虽然是临时解决方案,但可以保证程序在不同 Linux 桌面环境下的正常运行。
===
知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 0xJins
(包含此链接),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。