The new packaged OSX mono runtime is throwing an exception when trying to determine the hostname, with the following code:
var localhost = Dns.GetHostName();
The exception throws is as follows:
System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system. ---> System.Exception: The 'ExeConfigFilename' argument cannot be null.
at System.Configuration.ExeConfigurationHost.CheckFileMap (ConfigurationUserLevel level, System.Configuration.ExeConfigurationFileMap map) [0x0002b] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/InternalConfigurationHost.cs:293
at System.Configuration.ExeConfigurationHost.InitForConfiguration (System.String& locationSubPath, System.String& configPath, System.String& locationConfigPath, IInternalConfigRoot root, System.Object hostInitConfigurationParams) [0x00036] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/InternalConfigurationHost.cs:338
at System.Configuration.InternalConfigurationSystem.InitForConfiguration (System.String& locationConfigPath, System.String& parentConfigPath, System.String& parentLocationConfigPath) [0x00000] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/InternalConfigurationFactory.cs:67
at System.Configuration.Configuration..ctor (System.Configuration.InternalConfigurationSystem system, System.String locationSubPath) [0x0001f] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/Configuration.cs:86
at System.Configuration.InternalConfigurationFactory.Create (System.Type typeConfigHost, System.Object hostInitConfigurationParams) [0x0000e] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/InternalConfigurationFactory.cs:42
at System.Configuration.ConfigurationManager.OpenExeConfigurationInternal (ConfigurationUserLevel userLevel, System.Reflection.Assembly calling_assembly, System.String exePath) [0x00124] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/ConfigurationManager.cs:119
at System.Configuration.ClientConfigurationSystem.get_Configuration () [0x00011] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/ClientConfigurationSystem.cs:51
--- End of inner exception stack trace ---
at System.Configuration.ClientConfigurationSystem.get_Configuration () [0x00025] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/ClientConfigurationSystem.cs:54
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection (System.String configKey) [0x00000] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/ClientConfigurationSystem.cs:63
at System.Configuration.ConfigurationManager.GetSection (System.String sectionName) [0x00006] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System.Configuration/System.Configuration/ConfigurationManager.cs:162
at System.Net.Sockets.Socket.CheckProtocolSupport () [0x0003c] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System/System.Net.Sockets/Socket_2_1.cs:798
at System.Net.Sockets.Socket..cctor () [0x0000c] in /private/tmp/source/bockbuild/profiles/mono-mac-release/build-root/mono-3.0.3/_build/mono-3.0.3.git/mcs/class/System/System.Net.Sockets/Socket_2_1.cs:778
This mac is connected to the internet and also has a proper hostname:
yume:Libraries jshore$ hostname
Somehow the protocol support check is failing.
I should note that I had this behavior from an application which is linking to C# (libmono-2.0) (i.e. using mono in an embedded fashion). This aoplication was working in older versions of the VM.
I note that it throws the exception:
System.Exception: The 'ExeConfigFilename' argument cannot be null.
within the ExeConfigurationHost class, CheckFileMap () method.
I am guessing it is trying to find the exe configuration file. Am not sure why this mapping is passed in as null.
I noticed that someone else has the same problem and commented on github. The following was suggested to the other respondent by baulig:
When taking the code path from your stack trace, the only way you could possibly get there with ExeConfigFileName == null is if AppDomain.CurrentDomain.SetupInformation.ConfigurationFile == null - and the only way of achieving that is calling the unmanaged mono_domain_create_appdomain (char *friendly_name, char *configuration_file) with a NULL argument.
It's normally set in mono_runtime_exec_main() by appending ".config" to the assembly filename.
I think FreeSWITCH should call mono_domain_create_appdomain() to create a domain and specify the configuration file. The file does not need to exist, but you have to tell the configuration system where to look for it.
As a workaround, we could also add a check here and set an arbitrary name like "app.config" if AppDomain.CurrentDomain.SetupInformation.ConfigurationFile == null.
Here is my followup comment there:
"I am having the same problem with an application that embeds mono. This application has been working fine in prior versions. There is no explicit call to: mono_domain_create_appdomain().
Rather the following is done:
_domain = mono_jit_init (bootassembly);
_core = mono_domain_assembly_open (_domain, bootassembly);
bootassembly is the path the the main assembly to be used. I would have thought that mono_jit_init() would create an AppDomain and set the appropriate structure.
Finally, this is the approach outlined in http://www.mono-project.com/Embedding_Mono. Suggest doing the workaround as suggested above or making sure that the above embedded mono C-api calls create the app domain with the app domain name filled in."
mono_jit_init() eventually creates the AppDomain with:
mono_init_from_assembly (filename, filename);
mono_init_internal (domain_name, filename, NULL);
which sets up the domain structures, etc. It seems to me that these calls are probably not setting up the configuration location.
In any case, changing the C# configuration code to be resilient is probably the right thing to do.
Created attachment 3430 [details]
proposed patch for this bug
I have a simple patch that detects a configuration exception (if the configuraton is not present) and continues on the the next ipv6 test.
What's the exception raised that you're catching in the catch block? It would be better to be specific, not just catch the generic "Exception". Also, you have some spaces, when you should be using tabs. And cannot the try-catch block focus on a smaller piece of code? Surely the exception you noticed only happened in one of those lines.
The exception is: System.Configuration.ConfigurationErrorsException. However this involves adding a library dependency if I recall. I did not know what to change in order to add this additional library into the class build. I don't understand the build process for this. Appreciate your adjustments, kindly.
Both config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection() AND NetConfig config = System.Configuration.ConfigurationSettings.GetConfig(() can throw an exception.
Could double up a try/catch or just have one across these 2 calls, whichever you prefer. There are only 4 real lines of code here.
Oh good point about the dependency. I guess you can then use the generic catch(Exception), but then put a comment saying that the actual exception is ConfigurationErrorsException.
BTW, if you add a unit test (that passes on .NET and fails on Mono without the bugfix) to the mono test suite in your patch, and you post the patch as a pull request on github, it will have higher chances to be included upstream.
Thanks for the advice. The unit test cannot be done as a C# test. The problem occurs only with embedded applications, because embedded applications have no application config set up.
Regardless, the expected behavior of the config calls is that they can emit the above exception. We should be guarding against that and allow this static initializer to proceed.
What would you recommend in getting this in? This bug has been reported on discussions in github (by another developer as well), but is hard to show as a unit test, unless unit tests include the much more compllex, embedded applications.
FYI if you call mono_domain_create_appdomain() yourself, you DO have to have a valid config file with a <configuration/> block, or you will get errors saying the ApplicationBase must be set when the configuration manager tries to access various settings.
Being that this whole issue breaks pretty much anything using network calls, the embedding docs should be updated until this gets fixed. I wasted a good amount of time on this basically because of bad documentation.