Mono 1.2.6 and Ice

in Bug Reports
Hi,
I have updated Mono on my machine (running Gentoo) to version 1.2.6 and executing my application (wich is using Ice) returns this exception:
Did you tried mono 1.2.6? Is it bug on their side or yours? Thanks
I have updated Mono on my machine (running Gentoo) to version 1.2.6 and executing my application (wich is using Ice) returns this exception:
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object at IceInternal.Network.fdToString (System.Net.Sockets.Socket socket) [0x00000] at IceInternal.TcpTransceiver..ctor (IceInternal.Instance instance, System.Net.Sockets.Socket fd) [0x00000] at IceInternal.TcpConnector.connect (Int32 timeout) [0x00000] at IceInternal.OutgoingConnectionFactory.create (IceInternal.EndpointI[] endpts, Boolean hasMore, Boolean threadPerConnection, System.Boolean& compress) [0x00000] at IceInternal.RoutableReference.createConnection (IceInternal.EndpointI[] allEndpoints, System.Boolean& comp) [0x00000] at IceInternal.DirectReference.getConnection (System.Boolean& comp) [0x00000] at Ice.ObjectDelM_.setup (IceInternal.Reference rf) [0x00000] at Ice.ObjectPrxHelperBase.getDelegate__ () [0x00000] at Ice.LocatorPrxHelper.findObjectById (Ice.Identity id, Ice.Context context__, Boolean explicitContext__) [0x00000] at Ice.LocatorPrxHelper.findObjectById (Ice.Identity id) [0x00000] at IceInternal.LocatorInfo.getEndpoints (IceInternal.IndirectReference ref, Int32 ttl, System.Boolean& cached) [0x00000] at Ice.ObjectAdapterI.isLocal (ObjectPrx proxy) [0x00000] at IceInternal.ObjectAdapterFactory.findObjectAdapter (ObjectPrx proxy) [0x00000] at Ice.ObjectPrxHelperBase.getDelegate__ () [0x00000] at Ice.ObjectPrxHelperBase.ice_isA (System.String id__, Ice.Context context__, Boolean explicitContext__) [0x00000] at Ice.ObjectPrxHelperBase.ice_isA (System.String id__) [0x00000] at IceGrid.QueryPrxHelper.checkedCast (ObjectPrx b) [0x00000]
Did you tried mono 1.2.6? Is it bug on their side or yours? Thanks
0
Comments
Cheers,
Michi.
One could argue that this is not a bug because .NET does the same thing :mad:
If you look in Network.cs, around line 1320, you will find a number of DllImport statements. You need to replace these with the name of your C library, for example
Do the same for the getpeername, inet_ntoa, and ntohs imports.
Then change the definitions of getLocalAddress and getRemoteAddress as follows:
This fixes the problem. I'm not entirely happy with this P/Invoke fix though because the library name is platform dependent :mad:
For the moment, this fix should get you off the hook. I'll talk to the Mono people to see whether there is a better way to do this.
Cheers,
Michi.
thank you.
But I don't like the fix. I would like to use the same icecs.dll on both Linux and Windows in my application.
so I don't like this:
#if __MonoCS__
I found that you use it only in src\Ice\Application.cs. Can you remove it? I use Mono also on Windows so it is not the right swich and such switches should be done at runtime not at compilation time.
You can for example define the methods twice in different classes with the same interface and at runtime check the platform...
thanks
I don't like it either. But I'm afraid that there is no way to avoid this if we are forced to use P/Invoke because of a deficiency in .NET.
No, we use P/Invoke in a number of places, not just Application.cs.
I agree that this would be preferable. But there is no mechanism in the language to delay this decision until run time. The DllImport mechanism is hopelessly broken because it requires the library name to be hardwired into the code at compile time. What really should be there is a mechanism that can accept more than one library name at run time, and search a number of libraries for a particular symbol, similar to LD_LIBRARY_PATH.
As far as I know, that's not possible for P/Invoke. But, if you have a solution to this, I'd be keen to hear about it!
Cheers,
Michi.
CodeProject: Late binding on native DLLs with C#. Free source code and programming articles
Michi.
It is true that the DllImport "requires the library name to be hardwired into the code at compile time", but the DllImport loads the library first time the method is called! So if you have in the code methods with the DllImport attribute for both linux and windows and you call only these which are in actual platform everything works.
Then the code can select which function to call at run time.
This is a little better than #if __MonoCS__, but still has the disadvantage of hard-wiring the name of the C library.
And, due to the limitations of the C# preprocessor, we cannot define the name of the library in the makefile and then substitute it into the code. As far as I can see, the only way to use a DllImport attribute is to have the name of the library as a string literal in the program text :mad:
Cheers,
Michi.
Read Interop with Native Libraries - Mono. You can specify only a name without sufixes and prefixes, so if I uderstand correctly this is the right way for the libc.so.6: You can later override the name in mono by <dllmap/> elements in the .config file... Still not best, but better than nothing.
And getsocknameGnu or getsocknameUnix (the same name as in System.PlatformID enumeration) is better name for that method, because if you are running Mono on windows this method should not be called.
Now that looks promising. I'll have a close look at that, thanks a lot!
Cheers,
Michi.
thanks,
Michal
I saw this discussion late. Anyway, it would be on my wishlist if IceCS could be fully managed code, because than it could run in security restricted situations, where P/Invoke is not allowed.
Regarding the issue at hand - Mono duplicating a .NET bug/deficiency, I ran your test code which I found on Google, where you demonstrated that a non-blocking socket will have null endpoint properties even if the Poll succeeded:
Sockets and non-blocking connect - .NET C#
I then added a simple Bind call with unspecified address and port -- s.Bind(new IPEndPoint(IPAddress.Any, 0)); -- before calling connect, and then both local and remote endpoints were not null.
Could that work for you?
Karl
We are using P/Invoke in a number of other places to work around limitations of .NET, and we also use P/Invoke for protocol compression. Getting rid of all of these might be difficult.
Cheers,
Michi.
It probably requires some study as to which managed API is a good replacement for some of your interop calls. I just had a quick look, and maybe there are a few avenues worth looking at:
1) For SetConsoleCtrlHandler, the Console.CancelKeyPressEvent would be an alternative, as long as all you care about is capturing Ctrl+C and Ctrl+Break.
2) It looks as if Guid.NewGuid() does the same as UUIDCreate in rpcrt4.dll.
3) It seems there is also a managed alternative for libbz2.dll:
.NET Zip Library #ziplib (SharpZipLib)
Karl
What environments you are considering that require fully manged code?
We have an internal ASP.NET site that runs assemblies in semi-trusted mode. That excludes unsafe code and native interop. We are also considering running one of our apps from a web server (to simplify deployment). Though this app is currently not using ICE, I would not want to exclude ICE in the future simply because it can only run in a fully trusted context. I would also think that in Silverlight 2.0 (which apparently will have Socket support) using full IceCS instead of the HTTP bridge would be advantageous.
I have looked at your ByteBuffer class, the only place where I found unsafe code. I think the overall performance impact might not be as bad. It appears the unsafe code is mostly used for marshaling value types. For example, once could replace the unsafe getShort() and putShort() methods with this (untested!) code:
with no significant performance loss.
Karl
It will still be difficult to get rid off all the P/Invoke code though. We are using it for monotonic time, and CancelKeyPressEvent doesn't deal with window closure, logoff, and shutdown events (which SetConsoleCtrlHandler does).
Cheers,
Michi.
Its also possible to use BitConverter. At any rate, for sure its slower depending on what your application is doing (for example, marshaling an array of shorts or similar). The question is whether this matters to you
From my experience, .NET optimizes quite well, and since there is also a little overhead pinning memory (as in the 'fixed' statement), I did some benchmarking myself, using your ByteBuffer, but adding safe variants of putInt(), getInt(), putIntSeq() and getIntSeq(). I thought a performance difference would show up more clearly for ints than for shorts. The safe variants are coded like what I outlined previously. I built the app under VS 2005 in release mode, as debug mode is actually slower for this kind of application.
In my measurements, the safe code was most of the time *faster* than the unsafe code (it varied from one test run to the other). I also uncovered one specific *huge* performance issue with your code: if it has to reverse the byte order, the unsafe code is more than 10 times as slow as the safe code. This is normally the case on little-endian CPUs, i.e. almost always. The reason I think is the use of all those Buffer.SetByte/GetByte calls that are obviously not inlined by the compiler.
My CPU is an Athlon x64 dual core 3600.
If you like, I can send you the VS 2005 project (just tell where to) so that you can check for yourself and try it on other CPUs.
Karl
I could not find any P/Invoke calls that are time related. Where should I look?
Regarding SetConsoleCtrlHandler : It is only used in your helper class, so it is not an essential part of IceCS. Maybe one could spin off non-essential classes into a separate assembly?
Karl
I benchmarked this fairly extensively when I initially wrote the C# implementation. Back then, the unsafe version was faster than than the safe one. But that was several iterations of the compiler and run time ago, so this may have changed in the mean time.
I'll have a look at this too. It may well be that doing this differently will be faster now with the later version of the compiler and run time. Note that the byte order on the wire is little-endian--for little-endian CPUs, no byte swapping should take place.
Yes, that would be useful. Can you just email me the code please?
Thanks,
Michi.
I e-mailed the code to the e-mail address on your home page, hope that is the correct one.
Karl