AvaloniaUI/Avalonia · error · PlatformNotSupportedException

musl doesn't support RTLD_DEEPBIND

Error message

musl doesn't support RTLD_DEEPBIND

What it means

HarfbuzzWorkaround.Apply reloads libHarfBuzzSharp.so with RTLD_DEEPBIND to win the symbol-resolution race with Avalonia's own Skia/HarfBuzz. RTLD_DEEPBIND is a glibc-only flag and is not implemented by musl (Alpine Linux), so the code hard-fails on musl runtimes before attempting any load.

Source

Thrown at samples/XEmbedSample/HarfbuzzWorkaround.cs:44

 */
 
public unsafe class HarfbuzzWorkaround
{
    [DllImport("libc")]
    static extern int dlinfo(IntPtr handle, int request, IntPtr info);

    [DllImport("libc")]
    static extern IntPtr dlopen(string filename, int flags);

    private const int RTLD_DI_ORIGIN = 6;
    private const int RTLD_NOW = 2;
    private const int RTLD_DEEPBIND = 8;
    
    public static void Apply()
    {
        if (RuntimeInformation.RuntimeIdentifier.Contains("musl"))
            throw new PlatformNotSupportedException("musl doesn't support RTLD_DEEPBIND");
        
        var libraryPathBytes = Marshal.AllocHGlobal(4096);
        var handle = NativeLibrary.Load("libHarfBuzzSharp", typeof(HarfBuzzSharp.Blob).Assembly, null);
        dlinfo(handle, RTLD_DI_ORIGIN, libraryPathBytes);
        var libraryOrigin = Marshal.PtrToStringUTF8(libraryPathBytes) ?? string.Empty;
        Marshal.FreeHGlobal(libraryPathBytes);
        var libraryPath = Path.Combine(libraryOrigin, "libHarfBuzzSharp.so");
        
        NativeLibrary.Free(handle);
        var forceLoadedHandle = dlopen(libraryPath, RTLD_NOW | RTLD_DEEPBIND);
        if (forceLoadedHandle == IntPtr.Zero)
            throw new DllNotFoundException($"Unable to load {libraryPath} via dlopen");
        
        NativeLibrary.SetDllImportResolver(typeof(HarfBuzzSharp.Blob).Assembly, (name, assembly, searchPath) =>
        {
            if (name.Contains("HarfBuzzSharp"))
                return dlopen(libraryPath, RTLD_NOW | RTLD_DEEPBIND);
            return NativeLibrary.Load(name, assembly, searchPath);

View on GitHub (pinned to 11c5427268)

Solutions

  1. Run on a glibc-based distro (Debian/Ubuntu/Fedora) where RTLD_DEEPBIND is supported.
  2. Use a glibc-based base image instead of an Alpine one for the app.
  3. Skip Apply() on musl and rely on Avalonia's bundled HarfBuzz (remove the deepbind workaround).
  4. If deepbind is required, port the workaround to a musl-compatible mechanism (RTLD_LOCAL preloading / symbol interposition).

Example fix

// before
if (RuntimeInformation.RuntimeIdentifier.Contains("musl"))
    throw new PlatformNotSupportedException("musl doesn't support RTLD_DEEPBIND");

// after (no-op on musl instead of hard-failing)
if (RuntimeInformation.RuntimeIdentifier.Contains("musl"))
    return; // deepbind workaround is glibc-only; musl uses the bundled HarfBuzz as-is
Defensive patterns

Strategy: fallback

Validate before calling

// skip the workaround on musl
if (RuntimeInformation.RuntimeIdentifier.Contains("musl"))
{ /* use bundled HarfBuzz as-is; do not call Apply() */ }

Type guard

static bool IsMusl() => RuntimeInformation.RuntimeIdentifier.Contains("musl");

Try / catch

try { HarfbuzzWorkaround.Apply(); }
catch (PlatformNotSupportedException ex) when (ex.Message.Contains("musl"))
{ /* acceptable on musl; bundled HarfBuzz is used */ }

Prevention

When it happens

Trigger: Calling HarfbuzzWorkaround.Apply() on a .NET runtime whose RuntimeIdentifier contains 'musl' (Alpine/musl-based images). The guard throws immediately because the workaround's mechanism (deepbind) cannot exist there.

Common situations: Running an Avalonia Linux app inside an Alpine Docker container or any musl-based distro; .NET musl RIDs (linux-musl-x64 / linux-musl-arm64).

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/841c778c06f8dce6. Report an issue: GitHub.