Skip to content

Load a png on IOS causes an "Attempting to JIT compile method while running in aot-only mode" #776

Closed

Description

@vicfergar

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

Description

When trying to load a PNG image on iOS 12 an unhandled exception is raised.

Steps to Reproduce

On an Xamarin.IOS project try to invoke:
var image = SixLabors.ImageSharp.Image.Load(stream);

The next exception will be raised:

System.ExecutionEngineException: Attempting to JIT compile method 'SixLabors.ImageSharp.Formats.Png.PngScanlineProcessor:ProcessRgbScanline<SixLabors.ImageSharp.PixelFormats.Rgba32> (SixLabors.ImageSharp.Configuration,SixLabors.ImageSharp.Formats.Png.PngHeader&,System.ReadOnlySpan`1<byte>,System.Span`1<SixLabors.ImageSharp.PixelFormats.Rgba32>,int,int,bool,SixLabors.ImageSharp.PixelFormats.Rgb48,SixLabors.ImageSharp.PixelFormats.Rgb24)' while running in aot-only mode. See https://developer.xamarin.com/guides/ios/advanced_topics/limitations/ for more information.

  at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ProcessDefilteredScanline[TPixel] (System.ReadOnlySpan`1[T] defilteredScanline, SixLabors.ImageSharp.ImageFrame`1[TPixel] pixels) [0x000db] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at (wrapper unknown) System.Object.gsharedvt_in()
  at (wrapper unknown) System.Object.gsharedvt_out()
  at SixLabors.ImageSharp.Formats.Png.
PngDecoderCore.DecodePixelData[TPixel] (System.IO.Stream compressedStream, SixLabors.ImageSharp.ImageFrame`1[TPixel] image) [0x000e5] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at (wrapper unknown) System.Object.gsharedvt_in()
  at (wrapper unknown) System.Object.gsharedvt_out()
  at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadScanlines[TPixel] (System.IO.Stream dataStream, SixLabors.ImageSharp.ImageFrame`1[TPixel] image) [0x00017] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at (wrapper unknown) System.Object.gsharedvt_in()
  at (wrapper unknown) System.Object.gsharedvt_out()
  at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Decode[TPixel] (System.IO.Stream stream) [0x00171] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at (wrapper unknown) System.Object.gsharedvt_in()
  at (wrapper unknown) System.Object.gsharedvt_out()
  at SixLabors.ImageSharp.Formats.Png.PngDecoder.Decode[TPixel] (SixLabors.ImageSharp.Configuration configuration, System.IO.Stream stream) [0x00008] in <eb47c90af2ba451c9c07fe98c40e78
10>:0 
  at SixLabors.ImageSharp.Image.Decode[TPixel] (System.IO.Stream stream, SixLabors.ImageSharp.Configuration config) [0x00015] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at SixLabors.ImageSharp.Image+<>c__DisplayClass55_0`1[TPixel].<Load>b__0 (System.IO.Stream s) [0x00000] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at SixLabors.ImageSharp.Image.WithSeekableStream[T] (SixLabors.ImageSharp.Configuration config, System.IO.Stream stream, System.Func`2[T,TResult] action) [0x0002b] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at SixLabors.ImageSharp.Image.Load[TPixel] (SixLabors.ImageSharp.Configuration config, System.IO.Stream stream, SixLabors.ImageSharp.Formats.IImageFormat& format) [0x00022] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at SixLabors.ImageSharp.Image.Load[TPixel] (SixLabors.ImageSharp.Configuration config, System.IO.Stream stream) [0x00000] in <eb47c90af2ba451c9c07fe98c40e7810>:0 
  at SixLabors.ImageSharp.Image.Load[TPixel] (System.IO.Stream stream) [0x00000] in <eb47c90af2ba451c9c07fe98c40e78
10>:0 
  at SixLabors.ImageSharp.Image.Load (System.IO.Stream stream) [0x00000] in <eb47c90af2ba451c9c07fe98c40e7810>:0 

System Configuration

  • ImageSharp version: 1.0.0-beta0005
  • Other ImageSharp packages and versions: (none)
  • Environment (Operating system, version and so on): iOS 12
  • .NET Framework version:
  • Additional information:
    === Visual Studio Enterprise 2017 for Windows ===
    Version 15.8.9
    VisualStudio.15.Release/15.8.9+28010.2050
    Xamarin 4.11.0.779 (d15-8@ff915e800)
    Xamarin.iOS and Xamarin.Mac SDK 12.1.0.15 (cbfb047)

Activity

  1. vicfergar commented on Nov 14, 2018

    @vicfergar
    Author

    This is related with #383 and #762

  2. antonfirsov commented on Nov 22, 2018

    @antonfirsov
    Member

    @vicfergar I wonder how should we extend the AOT seeding utility introduced in #767 to make this work.

    We lack both the knowledge and the time to investigate this, so any hints from the community would be very helpful.

  3. davilovick commented on Jan 31, 2019

    @davilovick

    I've just tried to load a PNG in iOS with the latest Release (1.0.0-beta0006), and the issue is still happening.

    The stacktrace is exatly the same that @vicfergar has described.

  4. James-Jackson-South commented on Jan 31, 2019

    @James-Jackson-South

    Did you use the seed utility method?

  5. davilovick commented on Feb 4, 2019

    @davilovick

    Sorry for the delay.

    Yes, I've used the Seed method. Here is an example of how I've used this to reproduce the problem:

            private static void SeedAOT()
            {
                AotCompilerTools.Seed<Rgba32, Rgb24, Bgr24>();
                AotCompilerTools.Seed<Rgb48, Bgra32, Gray8>();
            }
    
            public ViewController (IntPtr handle) : base (handle)
            {
                SeedAOT();
            }
    
  6. leonluc-dev commented on Jul 11, 2019

    @leonluc-dev

    I'm encountering a similar issue in my iOS app.
    I use the following code in a .NET Standard project (referenced by an Xamarin.iOS and Xamarin.Android app) to load a PNG or JPEG image from a byte array.

    var image = Image.Load(imageBytes)
    

    This works fine for JPEG images (and on the Android app), but as soon as I try to load PNG image data on iOS the following exception occurs:

    Unhandled managed exception: Attempting to JIT compile method 'SixLabors.ImageSharp.Formats.Png.PngScanlineProcessor:ProcessRgbaScanline<SixLabors.ImageSharp.PixelFormats.Rgba32> (SixLabors.ImageSharp.Configuration,SixLabors.ImageSharp.Formats.Png.PngHeader&,System.ReadOnlySpan`1<byte>,System.Span`1<SixLabors.ImageSharp.PixelFormats.Rgba32>,int,int)' while running in aot-only mode. See https://docs.microsoft.com/xamarin/ios/internals/limitations for more information.
     (System.ExecutionEngineException)
      at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ProcessDefilteredScanline[TPixel] (System.ReadOnlySpan`1[T] defilteredScanline, SixLabors.ImageSharp.ImageFrame`1[TPixel] pixels, SixLabors.ImageSharp.Formats.Png.PngMetaData pngMetaData) [0x00135] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.DecodePixelData[TPixel] (System.IO.Stream compressedStream, SixLabors.ImageSharp.ImageFrame`1[TPixel] image, SixLabor
    s.ImageSharp.Formats.Png.PngMetaData pngMetaData) [0x000e5] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadScanlines[TPixel] (System.IO.Stream dataStream, SixLabors.ImageSharp.ImageFrame`1[TPixel] image, SixLabors.ImageSharp.Formats.Png.PngMetaData pngMetaData) [0x00018] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Decode[TPixel] (System.IO.Stream stream) [0x00171] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Formats.Png.PngDecoder.Decode[TPixel] (SixLabors.ImageSharp.Configuration configuration, System.IO.Stream stream) [0x00008] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Image.Decode[TPixel] (System.IO.Stream stream, SixLabors.ImageSharp.Configuration config) [0x00015] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Image+<>c__DisplayClass55_0`1[TPixel].<Load>b__0 (System.IO.Stream s) [0x00000] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLa
    bors.ImageSharp.Image.WithSeekableStream[T] (SixLabors.ImageSharp.Configuration config, System.IO.Stream stream, System.Func`2[T,TResult] action) [0x0002b] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Image.Load[TPixel] (SixLabors.ImageSharp.Configuration config, System.IO.Stream stream, SixLabors.ImageSharp.Formats.IImageFormat& format) [0x00022] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Image.Load[TPixel] (SixLabors.ImageSharp.Configuration config, System.IO.Stream stream) [0x00000] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Image.Load[TPixel] (SixLabors.ImageSharp.Configuration config, System.Byte[] data) [0x00007] in <7430a37e6bca4100b1763856ff8f7867>:0 
      at SixLabors.ImageSharp.Image.Load (System.Byte[] data) [0x00005] in <7430a37e6bca4100b1763856ff8f7867>:0 
    

    This exception seems close to identical to the one described in this issue. The major difference being the method name ProcessRgbaScanline vs ProcessRgbScanline

    I've already tried using the AotCompilerTools to seed the Rgba32 pixel type my code uses, but this did not solve the issue.

    private static void NeverCallThisMethod()
    {
        AotCompilerTools.Seed<Rgba32>();
        throw new Exception("Don't call AotCompilerTools.NeverCallThisMethod(), it only exists to preseed the AOT compiler.");
            }
    
  7. leonluc-dev commented on Jul 12, 2019

    @leonluc-dev

    Looking into it, it seems the following code is not properly seeded for some reason (possibly due to the inferred generics, but I'm not 100% sure):

    switch (this.pngColorType)
    {
    case PngColorType.Grayscale:
    PngScanlineProcessor.ProcessGrayscaleScanline(
    this.header,
    scanlineSpan,
    rowSpan,
    pngMetadata.HasTrans,
    pngMetadata.TransparentGray16.GetValueOrDefault(),
    pngMetadata.TransparentGray8.GetValueOrDefault());
    break;
    case PngColorType.GrayscaleWithAlpha:
    PngScanlineProcessor.ProcessGrayscaleWithAlphaScanline(
    this.header,
    scanlineSpan,
    rowSpan,
    this.bytesPerPixel,
    this.bytesPerSample);
    break;
    case PngColorType.Palette:
    PngScanlineProcessor.ProcessPaletteScanline(
    this.header,
    scanlineSpan,
    rowSpan,
    this.palette,
    this.paletteAlpha);
    break;
    case PngColorType.Rgb:
    PngScanlineProcessor.ProcessRgbScanline(
    this.configuration,
    this.header,
    scanlineSpan,
    rowSpan,
    this.bytesPerPixel,
    this.bytesPerSample,
    pngMetadata.HasTrans,
    pngMetadata.TransparentRgb48.GetValueOrDefault(),
    pngMetadata.TransparentRgb24.GetValueOrDefault());
    break;
    case PngColorType.RgbWithAlpha:
    PngScanlineProcessor.ProcessRgbaScanline(
    this.configuration,
    this.header,
    scanlineSpan,
    rowSpan,
    this.bytesPerPixel,
    this.bytesPerSample);
    break;

    Since the code is marked assembly internal I cannot directly seed these methods without importing/modifying the source code.

  8. antonfirsov commented on Jul 14, 2019

    @antonfirsov
    Member

    @gameleon-dev thans for the investigations you made so far! 👍
    I have just opened #946 to address this issue at a higher level. Let's continue the discussion there!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions