Bug 22140 - Failure to load mono-supplied .dylib when running from console.
Summary: Failure to load mono-supplied .dylib when running from console.
Alias: None
Product: Runtime
Classification: Mono
Component: Interop ()
Version: unspecified
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2014-08-15 18:50 UTC by Brian Berry
Modified: 2014-10-04 11:10 UTC (History)
5 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Brian Berry 2014-08-15 18:50:26 UTC
Observed: Failure to load as-installed libgdiplus.dylib when running from console.

Steps to reproduce:
  * Create a simple console app that relies upon System.Drawing to create a Bitmap.
  * Run the sample from the debugger and observe success.
  * Run the same app from a shell "/usr/bin/mono <myassembly>" from the assembly path.
  * Note an exception as below:

Unhandled Exception:
System.TypeInitializationException: An exception was thrown by the type initializer for System.Drawing.GDIPlus ---> System.DllNotFoundException: libgdiplus.dylib
  at (wrapper managed-to-native) System.Drawing.GDIPlus:GdiplusStartup (ulong&,System.Drawing.GdiplusStartupInput&,System.Drawing.GdiplusStartupOutput&)
  at System.Drawing.GDIPlus..cctor () [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Drawing.Bitmap..ctor (System.String filename, Boolean useIcm) [0x00000] in <filename unknown>:0 
  at System.Drawing.Bitmap..ctor (System.String filename) [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) System.Drawing.Bitmap:.ctor (string)
 . . .

Expected: Mono's resolution of .dylib shouldn't depend upon debugger vs. not.

   * This console utility (something very like it, anyway) was working
     previously without this issue.
   * I do observe the .dylib in the expected install location:
   * I can sidestep this by copying/linking libgdiplus.dylib from its installed
     location to my assembly's location, but has something changed in
     the mono implementation regarding its .dylib search mechanism for
     built-in libs?
   * XS version below:

Xamarin Studio
Version 5.3 (build 423)
Installation UUID: b577b744-52dd-4f14-848b-8dcc8a961c91
	Mono 3.8.0 ((no/62a857e)
	GTK+ 2.24.23 (Raleigh theme)   

   * Mono runtime version below.

Mono JIT compiler version 3.8.0 ((no/62a857e Wed Aug 13 00:46:20 EDT 2014)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           normal
	SIGSEGV:       altstack
	Notification:  kqueue
	Architecture:  x86
	Disabled:      none
	Misc:          softdebug 
	LLVM:          yes(3.4svn-mono-(no/e656cac)
	GC:            sgen
Comment 1 Brian Berry 2014-08-15 19:45:13 UTC
I've resolved this by just linking that specific .dylib into the target directory as a post step---so feel free to mark as resolved if this is working as designed.   Just curious, though, about the distinction between running the exact command under the IDE vs. a shell.  Specifically, what rules the mono runtime follows for resolving the dynamic libraries that come with its own distribution (I'd think they would be implicit?)---and what you think the explanation might be for inconsistent behavior (IDE launch vs. not) in this case.

Much appreciated!
Comment 2 Brian Berry 2014-08-21 11:39:49 UTC
Additional note:  I just stumbled across logging from an assembly made nearly a year ago and is running under a cron job every minute.  It, too, suffers from the same issue---a console app unable to implicitly load/bind libgdiplus.dylib, same signature:

Exception: System.TypeInitializationException: An exception was thrown by the type initializer for System.Drawing.KnownColors ---> System.TypeInitializationException: An exception was thrown by the type initializer for System.Drawing.GDIPlus ---> System.DllNotFoundException: libgdiplus.dylib
  at (wrapper managed-to-native) System.Drawing.GDIPlus:GdiplusStartup (ulong&,System.Drawing.GdiplusStartupInput&,System.Drawing.GdiplusStartupOutput&)
  at System.Drawing.GDIPlus..cctor () [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Drawing.KnownColors..cctor () [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Drawing.Color.get_OrangeRed () [0x00000] in <filename unknown>:0 
  at <redacted>.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 

So this does appear to be due to a recent change in the mono runtime itself.
(This assembly just went from working -> not across one of the alpha channel
runtime updates....not touched/rebuilt/anything.)

Hope this helps!
Comment 3 Brian Berry 2014-08-30 12:35:27 UTC
Minimal steps to reproduce this issue:

Xamarin Studio
Version 5.3 (build 435)
	Mono 3.8.0 ((no/62a857e)
	GTK+ 2.24.23 (Raleigh theme)

(1) Launch XS.
(2) Create a new console application, default location is okay, name e.g. GDIPlusBug.
(3) Add to the project a reference to the System.Drawing assembly.
(4) Alter Program.cs to minimally invoke features of the System.Drawing, e.g.:

using System;
using System.Drawing; // ADDED

namespace GDIPlusBug
    class MainClass
        public static void Main(string[] args)
            var color = Color.Black; // ADDED

            Console.WriteLine("Hello World!");

(5) Start the debugging session.

You should observe a TypeInitializationException for KnownColors.
Then, the minimal hack fix for this issue is to:

(6) Open a terminal session, cd to the console app project location.
(7) cd to the binary location, e.g. GDIPlusBug/GDIPlusBug/bin/Debug
(8) symlink libgdiplus.dylib from its installed location to the current directory, e.g.:

ln -s /Library/Frameworks/Mono.framework/Versions/Current/lib/libgdiplus.dylib .

(9) Start another debug session within XS for the same test app.

Result: proper operation.
Comment 4 Otto G 2014-09-16 11:39:37 UTC

I can confirm that I see the same issue -- also with Mono 3.8.0 (the package that comes with Xamarin Studio).

$ mono --version
Mono JIT compiler version 3.8.0 ((no/45d0ba1 Tue Aug 26 20:33:43 EDT 2014)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           normal
	SIGSEGV:       altstack
	Notification:  kqueue
	Architecture:  x86
	Disabled:      none
	Misc:          softdebug 
	LLVM:          yes(3.4svn-mono-(no/e656cac)
	GC:            sgen

Also, the same workaround works for me, too. I.e.:

ln -s /Library/Frameworks/Mono.framework/Versions/Current/lib/libgdiplus.dylib .

I would have expected the following to have the same effect:

DYLD_LIBRARY_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib /usr/bin/mono Program.exe

But for some reason, it did not help when I tried it. (At other times, with locally compiled Mono, it has been necessary to specify DYLD_LIBRARY_PATH=/usr/local/bin, but I hardly know anything about dylib path resolution, so there might be some obvious reason for why it would not have any effect in this case.)
Comment 5 Brian Berry 2014-09-20 10:56:56 UTC
Good morning, everybody.

As of the Mono 3.10 push to the alpha channel late this week, this has regressed even FURTHER.

Prior to this bug report, libgdiplus would be found implicitly by the runtime, associated types could be used out of the box without extra steps.

At the time of this bug report, the type initializer exceptions noted above began to occur, could only be remedied by manually symlinking libgdiplus.dylib from the Mono installed location into, say, the folder where the binary that intends to use it resides.

Today, with Mono 3.10, *** this symlink hack no longer bypasses the issue ***.

The result is that the pipeline tools I have in play, e.g. ones that manipulate Bitmap objects, no longer function.

Unless I find another hack fix, this is currently a progress blocker.

An expedited fix is appreciated.
Please do not allow this defect to propagate further toward beta -> stable!
Comment 6 Brian Berry 2014-09-20 20:11:47 UTC
Folks, please review your 3.8.0 vs. 3.10.0 build.  Specifically:


-rwxr-xr-x  1 root  admin  556252 Aug 26 17:43 libgdiplus.0.dylib*
lrwxr-xr-x  1 root  admin      18 Sep 20 16:51 libgdiplus.dylib@ -> libgdiplus.0.dylib
-rwxr-xr-x  1 root  admin    1865 Aug 26 17:43 libgdiplus.la*


-rwxr-xr-x  1 root  admin  4132 Sep 17 15:47 libgdiplus.0.dylib*
lrwxr-xr-x  1 root  admin    18 Sep 20 16:40 libgdiplus.dylib@ -> libgdiplus.0.dylib
-rwxr-xr-x  1 root  admin  1879 Sep 17 15:47 libgdiplus.la*

Note the size change on libgdiplus.0.dylib.
An nm on the former reports 1709 symbols, the latter just a single one.

It seems you have allowed a dud library out in the wild---this speaks to a process issue,
unless there was a bulk move of code to another library and this is now a stub.

If it is truly undersized, suggestions:
   * Improve your build/CI process to include checks to ensure you have a fully viable build.
   * Unit tests for just about any libgdiplus feature should have caught this.

(I'll be looking at the mono repository to see if there is any more insight there.)
Comment 7 Brian Berry 2014-09-21 12:22:51 UTC
Additional notes:
  * Overlaying 3.8.0's libgdiplus* files on top of a 3.10.0 installation
  allows the test app indicated above to run so long as you run it from
  the debugger.
  * The test app still does not run from the console without the stated
  exception, indicating that the originally reported bug is still present.
Comment 8 Tim Van Wassenhove 2014-09-27 04:11:07 UTC
I can confirm the same issue as well. The workaround I used was the following:

Edit /Library/Frameworks/Mono.framework/Versions/3.8.0/etc/mono/config and replace the entries for libgdiplus:

<dllmap dll="gdiplus" target="/Library/Frameworks/Mono.framework/Versions/3.8.0/lib/libgdiplus.dylib" os="!windows"/>
    <dllmap dll="gdiplus.dll" target="/Library/Frameworks/Mono.framework/Versions/3.8.0/lib/libgdiplus.dylib"  os="!windows"/>
    <dllmap dll="gdi32" target="/Library/Frameworks/Mono.framework/Versions/3.8.0/lib/libgdiplus.dylib" os="!windows"/>
    <dllmap dll="gdi32.dll" target="/Library/Frameworks/Mono.framework/Versions/3.8.0/lib/libgdiplus.dylib" os="!windows"/>
Comment 9 Brian Berry 2014-09-27 12:08:59 UTC
@Tim:  This does in fact fix the issue when running from the XS debugger.   It is also what was changed by the mono team in the 3.8.0 -> 3.10.0 timeframe.   Thanks for confirming this on your end.   The original reported regression, however (run this same assembly via "mono <xxxx>" from a bash shell, no added environment path changes to find libgdiplus.so, etc.) remains.   So XS/the debugger is invoking mono in such a way that it finds all of its implied internal bits...console mono invocation has lost [at least part of] its ability to do so across some relatively recent mono version boundary.
Comment 10 Tim Van Wassenhove 2014-09-27 16:12:17 UTC
@Brian: Perhaps I misunderstand (not familiar with the mono source code), but for me the modifications to the config enable me to run apps  (Debug and Release builds) from the command line (eg: mono Blah.exe) again.
Comment 11 Brian Berry 2014-09-27 17:00:57 UTC
@Tim:  Nope, you didn't misunderstand---I misunderstood that you observe a fix both in-debugger as well as from command line.  I only see a fix within the debugger.   Confirm for me (at your leisure, mind you---this is not a blocking issue for me currently) that you have no local modifications to LD_LIBRARY_PATH or other environment changes that might make a difference?   This is a bit of a puzzle.  Cheers.
Comment 12 Tim Van Wassenhove 2014-09-27 17:58:12 UTC
(The only 'magic' that happened today is that Quartz notified my that an update was available and I installed that. Current version: XQuartz 2.7.7 (xorg-server 1.15.2))

I see nothing special in my environment. Here is the output from printenv 

tims-mbp:Release timvw$ printenv
Comment 13 Brian Berry 2014-09-27 18:24:22 UTC
Appreciate the words, Tim.  Thank you.   I'll have to look further once I can roll back to 3.8.0 (or when a fixed 3.10.0+ hits to resolve the unrelated empty-library issues.   I haven't changed my environment in any meaningful way either---it just started to happen here (cron jobs running long-reliable utility assemblies, custom build steps in XS running .net tools) when a runtime update landed.   Cheers.
Comment 14 Brian Berry 2014-10-04 11:10:07 UTC
With the fix in for https://bugzilla.xamarin.com/show_bug.cgi?id=23553, this issue also looks resolved so far.   Many thanks.