Any code which uses System.Drawing fails on CentOS 7.4 with the following exception:
Unhandled Exception: System.TypeInitializationException: The type initializer for 'Gdip' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'libdl': The specified module or one of its dependencies could not be found.
(Exception from HRESULT: 0x8007007E)
at Interop.Libdl.dlopen(String fileName, Int32 flag)
at System.Drawing.SafeNativeMethods.Gdip.LoadNativeLibrary()
at System.Drawing.SafeNativeMethods.Gdip..cctor()
--- End of inner exception stack trace ---
at System.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromFile(String filename, IntPtr& bitmap)
at System.Drawing.Bitmap..ctor(String filename, Boolean useIcm)
at gdiplus.Program.Main(String[] args) in /root/gdiplus/Program.cs:line 12
This is because by default libdl.so
doesn't exist on CentOS whereas libdl.so.2
does exist.
As a workaround you can symlink /lib64/libdl.so.2
to /lib64/libdl.so
.
ln -s /lib64/libdl.so.2 /lib64/libdl.so
Program.cs:
using System;
using System.Drawing;
namespace gdiplus
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var bitmap = new Bitmap("test.bmp");
}
}
}
Project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview1-25718-03"/>
</ItemGroup>
</Project>
/cc @safern
Related to dotnet/runtime#23786
The interop code tries various variations but .so.2 is not one of them. Perhaps it should be @stephentoub ?
One way to fix this could be to add dlopen
and dlsym
to System.Native, so that resolving dlopen
and dlsym
becomes a native code problem instead of a managed code problem.
It would fix the libdl.so
vs libdl.so.2
problem, as well as the FreeBSD problem where dlopen
lives in another library alltogether.
I could probably create a PR for that, let me know if this is the way you want to go.
This problem seems to reproduce on Debian as well. However linking libdl.so
to libdl.so.2
doesn't work.
@henkmollema what version of .NET Core are you using? @qmfrederik 's change above would be in master, not released yet.
@danmosemsft .NET Core 2.0.
@qmfrederik any thoughts?
I submitted PR dotnet/corefx#25134 but this was rejected in favor or a more generic API.
That API is being discussed in dotnet/runtime#20635 and is ready for review.
Once that API is approved we can implement it and consume it from System.Drawing.Common to properly fix this issue.
@henkmollema In the meanwhile, if you're on Ubuntu or Debian, you can try to install the libc6-dev package to get libdl.so.
For now I fall back to using CoreCompat.System.Drawing.V2
and running apt-get install -y libgdiplus
in my Docker file. Might try installing libc6-dev
some time.
Unfortunately System.Drawing.Common 4.5.0-preview1 is used in a referenced package. In this case iTextSharp.LGPLv2.Core 1.4.2, which I accidentally updated. I run the code in Docker with the microsoft/aspnetcore:2.0.5 image. This results in the same message:
Exception: System.TypeInitializationException: The type initializer for 'Gdip' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'libdl': The specified module or one of its dependencies could not be found.
(Exception from HRESULT: 0x8007007E)
at Interop.Libdl.dlopen(String fileName, Int32 flag)
at System.Drawing.SafeNativeMethods.Gdip.LoadNativeLibrary()
at System.Drawing.SafeNativeMethods.Gdip..cctor()
--- End of inner exception stack trace ---
at System.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0(Int32 width, Int32 height, Int32 stride, PixelFormat format, IntPtr scan0, IntPtr& bmp)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at WillowMedia.Common.Pdf.Barcode.BarcodeStamper.CreateCode(MemoryStream ms, Object model)
...
@PeterHagen Did you install libgdiplus and libc6-dev in your container?
@qmfrederik yes, both of them
Can you check whether the file /usr/lib/x86_64-linux-gnu/libdl.so
exists _inside_ your container? If it still fails, you can try setting LD_LIBRARY_PATH
to $LD_LIBRARY_PATH:/usr/lib/x86_64-linux-gnu
but that should be included already.
If that still fails, can you set the LD_DEBUG
environment variable to libs
in your Dockerfile, restart your container, and share the output?
I'm sorry, with the libc6-dev added, it does work now. Pushing the correct Dockerfile seems to be an issue on a day like this. Thanks for the comment. I tested it on a local and the production Docker environment
Moving to future since it depends on API: https://github.com/dotnet/corefx/issues/17135 being added.
On debian i did ln -s /lib/x86_64-linux-gnu/libdl.so.2 /lib/x86_64-linux-gnu/libdl.so
.
Should we add various common names using the current technique https://github.com/dotnet/corefx/pull/27208/files#diff-557c4f4a6ff1d5ead7c96e76cf005001R46 for libdl? In post 2.1, once dotnet/runtime#20635 is landed we can update this pattern for all dependency libs.
The problem with that technique is that it uses dlopen
to probe for different filenames for libssl
. Here, you're probing for dlopen
itself so that doesn't work.
in my case of Docker container with base image microsoft/aspnetcore:2.0.5
after running these commands the error disappear
$ ln -s /lib/x86_64-linux-gnu/libdl.so.2 /lib/x86_64-linux-gnu/libdl.so
$ apt update
$ apt install libgdiplus
$ ln -s /usr/lib/libgdiplus.so /lib/x86_64-linux-gnu/libgdiplus.so
It looks like 4.5.0 can't be used out of the box because of this.
Installing libc6-dev is an ugly workaround. Making symbolic links will conflict when libc6-dev is installed.
@sherlock1982 You are right, it's a bit of an ugly workaround. The structural fix is in https://github.com/dotnet/corefx/issues/17135. You can perhaps help accelerate a fix for that by upvoting the issue 😄 .
I am seeing this issue in running in OpenShift Containers... I have followed the instructions in this issue, my docker file now looks like this
RUN yum -y install \
..
libc6-dev \
libgdiplus \
..
&& yum clean all
RUN ln -s /usr/lib64/libdl.so.2 /usr/lib64/libdl.so
RUN ln -s /usr/lib64/libgdiplus.so.0.0.0 /usr/lib64/libgdiplus.so
The original error of "Unable to load DLL 'libdl…" disappears but now when I attempt to run my code I get
/docker-entrypoint.sh: line 3: 7 segmentation fault (core dumped) dotnet apihost.dll
The underlying OSis RHEL 7.4 (maipo) and using ASP .NET Core 2.1
Note this error happens in 1 in every 100 attempts to execute the offending code.
Any advice please
/docker-entrypoint.sh: line 3: 7 segmentation fault (core dumped) dotnet apihost.dll
This doesn't seem like an error in System.Drawing.Common itself. Could you please confirm if this happens in a single Console App, or if you could share a stack trace from the dump that would be super useful as well.
what is the recommended way to get a copy of the dump, I am not sure how I can get this because the container keeps crashing.
Just to also confirm the same code works on a windows running with IIS,
I have the same issue, with the docker image provided by microsoft I'm getting exceptions in my code:
System.DllNotFoundException : Unable to load shared library 'libdl' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibdl: cannot open shared object file: No such file or directory
So far the only workaround I've found is to extend from the provided docker-file and add libc6-dev with apt-get:
FROM microsoft/dotnet:2.1-sdk
# Dependencies for libraries
RUN apt-get update \
&& apt-get install -y --no-install-recommends libc6-dev
If I run my code in a container build from this dockerfile the exception is not thrown.
Still facing this issue using dotnet core 2.2.4, and debian image in Azure App Service
I suspect this might be solved when targeting .NET Core 3.0
and using the latest System.Drawing.Common
package in NuGet since we're no longer loading libgdiplus
directly with dlopen
but instead using the new Native Library Loader. Will try it out and close if fixed.
@safern , Did you try it out? Did that work with .Net Core 3.0?
@savanbthakkar I've migrated my application to .Net Core 3.0 and the problem is solved, but you have to have installed libgdiplus and libc6-dev anyway.
@joalcava Have you used System.Drawing in a Lambda function?
@joalcava Have you used System.Drawing in a Lambda function?
I have used in a Lambda function,I have the same errors
.NET Core 3.0
System.Drawing.Common from NuGet
An error on CentOS 7.
after The type initializer for 'Gdip' threw an exception.
An unhandled exception was thrown by the application.
Message: Parameter is not valid.
Source: System.Drawing.Common
StackTrace: at System.Drawing.SafeNativeMethods.Gdip.CheckStatus(Int32 status)
at System.Drawing.Bitmap.SetResolution(Single xDpi, Single yDpi)
at ImageProcessor.Common.Extensions.ImageExtensions.Copy(Image source, AnimationProcessMode animationProcessMode, PixelFormat format, Boolean preserveExifData)
at ImageProcessor.ImageFactory.Load(Image image)
UPD This was caused when using an image processor NuGet package from a plug-in with WebP. I think this should not work in .net core. Sorry for the mentions
Fixed in .NET Core 3.0
Most helpful comment
@henkmollema In the meanwhile, if you're on Ubuntu or Debian, you can try to install the libc6-dev package to get libdl.so.