diff options
-rwxr-xr-x | cs/src/Ice/Application.cs | 10 | ||||
-rw-r--r-- | cs/src/Ice/Assert.cs | 34 | ||||
-rw-r--r-- | cs/src/Ice/ConnectionFactory.cs | 31 | ||||
-rwxr-xr-x | cs/src/Ice/ConnectionI.cs | 55 | ||||
-rwxr-xr-x | cs/src/Ice/ConnectionMonitor.cs | 8 | ||||
-rwxr-xr-x | cs/src/Ice/EventHandler.cs | 15 | ||||
-rwxr-xr-x | cs/src/Ice/Ice.csproj | 5 | ||||
-rwxr-xr-x | cs/src/Ice/Instance.cs | 32 | ||||
-rwxr-xr-x | cs/src/Ice/ObjectAdapterFactory.cs | 12 | ||||
-rwxr-xr-x | cs/src/Ice/ObjectAdapterI.cs | 12 | ||||
-rwxr-xr-x | cs/src/Ice/ServantManager.cs | 2 | ||||
-rwxr-xr-x | cs/src/Ice/TcpAcceptor.cs | 6 | ||||
-rwxr-xr-x | cs/src/Ice/TcpTransceiver.cs | 6 | ||||
-rwxr-xr-x | cs/src/Ice/ThreadPool.cs | 6 | ||||
-rwxr-xr-x | cs/src/Ice/UdpTransceiver.cs | 6 |
15 files changed, 172 insertions, 68 deletions
diff --git a/cs/src/Ice/Application.cs b/cs/src/Ice/Application.cs index dfe326967c2..425a3621ae7 100755 --- a/cs/src/Ice/Application.cs +++ b/cs/src/Ice/Application.cs @@ -213,7 +213,7 @@ namespace Ice return rc; } -/* +#if !__MonoCS__ // // First-level handler // @@ -235,7 +235,7 @@ namespace Ice } return true; } -*/ +#endif // // The callbacks to be invoked from the handler. @@ -310,8 +310,10 @@ namespace Ice private static bool _nohup; private delegate Boolean EventHandler(int sig); - //private static readonly Application.EventHandler _handler - //= new Application.EventHandler(HandlerRoutine); // First-level handler +#if !__MonoCS__ + private static readonly Application.EventHandler _handler + = new Application.EventHandler(HandlerRoutine); // First-level handler +#endif private delegate void Callback(int sig); private static readonly Callback _destroyCallback = new Callback(destroyOnInterruptCallback); diff --git a/cs/src/Ice/Assert.cs b/cs/src/Ice/Assert.cs new file mode 100644 index 00000000000..d443c394efc --- /dev/null +++ b/cs/src/Ice/Assert.cs @@ -0,0 +1,34 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +namespace IceUtil +{ + + public sealed class Assert + { + // + // In C#, it's not safe to call *anything* from within a finalizer + // because the finalizer may run as part of process shutdown, and + // order of finalization is undefined. So, we don't run assertions + // once shutdown has started. + // + public static void + FinalizerAssert(bool b) + { + if(!b && !System.Environment.HasShutdownStarted) + { + System.Console.Error.WriteLine("Assertion failure:"); + + System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(true); + System.Console.Error.WriteLine(st); + } + } + } + +} diff --git a/cs/src/Ice/ConnectionFactory.cs b/cs/src/Ice/ConnectionFactory.cs index 91714335aaa..ee23575c0c4 100644 --- a/cs/src/Ice/ConnectionFactory.cs +++ b/cs/src/Ice/ConnectionFactory.cs @@ -60,8 +60,12 @@ namespace IceInternal // We want to wait until all connections are finished // outside the thread synchronization. // + // We set _connections to null rather than to a + // new empty list so that our finalizer does not try to invoke any + // methods on member objects. + // connections = _connections; - _connections = new Hashtable(); + _connections = null; } // @@ -497,15 +501,15 @@ namespace IceInternal _pending = new Set(); } +#if DEBUG ~OutgoingConnectionFactory() { -#if DEBUG lock(this) { - Debug.Assert(_destroyed); + IceUtil.Assert.FinalizerAssert(_destroyed); } -#endif DEBUG } +#endif private readonly Instance _instance; private bool _destroyed; @@ -531,7 +535,7 @@ namespace IceInternal } } - public void destroy() + public override void destroy() // TODO: should up-call here? { lock(this) { @@ -600,6 +604,16 @@ namespace IceInternal { connection.waitUntilFinished(); } + + // + // At this point we know that this factory is no longer used, so it is + // safe to invoke destroy() on the EventHandler base class to reclaim + // resources. + // + // We call this here instead of in the finalizer because a C# finalizer + // cannot invoke methods on other types of objects. + // + base.destroy(); } public Endpoint endpoint() @@ -888,10 +902,11 @@ namespace IceInternal #if DEBUG lock(this) { - Debug.Assert(_state == StateClosed); - Debug.Assert(_acceptor == null); + IceUtil.Assert.FinalizerAssert(_state == StateClosed); + IceUtil.Assert.FinalizerAssert(_acceptor == null); + IceUtil.Assert.FinalizerAssert(_connections != null); } -#endif DEBUG +#endif } private const int StateActive = 0; diff --git a/cs/src/Ice/ConnectionI.cs b/cs/src/Ice/ConnectionI.cs index 43e9cf748c3..6ab61c1563d 100755 --- a/cs/src/Ice/ConnectionI.cs +++ b/cs/src/Ice/ConnectionI.cs @@ -262,6 +262,8 @@ namespace Ice } } + cleanup(); + return true; } else @@ -356,6 +358,8 @@ namespace Ice _incomingCache = _incomingCache.next; } } + + cleanup(); } public void monitor() @@ -465,7 +469,26 @@ namespace Ice return uncompressed; } - + + /* + private class MessageInfo + { + MessageInfo(IceInternal.BasicStream stream) + { + this.stream = stream; + } + + IceInternal.BasicStream stream; + bool destroyStream; + int invokeNum; + int requestId; + byte compress; + IceInternal.ServantManager servantManager; + ObjectAdapter adapter; + IceInternal.OutgoingAsync outAsync; + } + */ + public void sendRequest(IceInternal.BasicStream os, IceInternal.Outgoing og, bool compress) { int requestId = 0; @@ -576,7 +599,7 @@ namespace Ice } finally { - if(!Object.ReferenceEquals(os, stream)) + if(stream != null && !Object.ReferenceEquals(os, stream)) { stream.destroy(); } @@ -1557,19 +1580,18 @@ namespace Ice } +#if DEBUG ~ConnectionI() { -#if DEBUG lock(this) { - Debug.Assert(_state == StateClosed); - Debug.Assert(_transceiver == null); - Debug.Assert(_dispatchCount == 0); + IceUtil.Assert.FinalizerAssert(_state == StateClosed); + IceUtil.Assert.FinalizerAssert(_transceiver == null); + IceUtil.Assert.FinalizerAssert(_dispatchCount == 0); + IceUtil.Assert.FinalizerAssert(_incomingCache == null); } -#endif DEBUG - - _batchStream.destroy(); } +#endif private const int StateNotValidated = 0; private const int StateActive = 1; @@ -1869,6 +1891,21 @@ namespace Ice _incomingCache = inc; } } + + private void cleanup() + { + // + // This should be called when we know that this object is no longer used, + // so it is safe to reclaim resources. + // + // We do this here instead of in a finalizer because a C# finalizer + // cannot invoke methods on other types of objects. + // + _batchStream.destroy(); + _batchStream = null; + + base.destroy(); + } private IceInternal.Transceiver _transceiver; private string _desc; diff --git a/cs/src/Ice/ConnectionMonitor.cs b/cs/src/Ice/ConnectionMonitor.cs index 063def16576..8b19d2af878 100755 --- a/cs/src/Ice/ConnectionMonitor.cs +++ b/cs/src/Ice/ConnectionMonitor.cs @@ -75,16 +75,16 @@ namespace IceInternal _thread.Start(); } +#if DEBUG ~ConnectionMonitor() { -#if DEBUG lock(this) { - Debug.Assert(_instance == null); - Debug.Assert(_connections != null); + IceUtil.Assert.FinalizerAssert(_instance == null); + IceUtil.Assert.FinalizerAssert(_connections != null); } -#endif DEBUG } +#endif public void Run() { diff --git a/cs/src/Ice/EventHandler.cs b/cs/src/Ice/EventHandler.cs index a5012caae0e..5add620a9da 100755 --- a/cs/src/Ice/EventHandler.cs +++ b/cs/src/Ice/EventHandler.cs @@ -57,6 +57,15 @@ namespace IceInternal return _instance; } + public virtual void destroy() + { + lock(this) + { + _stream.destroy(); + _stream = null; + } + } + protected internal EventHandler(Instance instance) { _instance = instance; @@ -65,8 +74,10 @@ namespace IceInternal ~EventHandler() { - Debug.Assert(_stream != null); - _stream.destroy(); + lock(this) + { + IceUtil.Assert.FinalizerAssert(_stream != null); + } } protected internal Instance _instance; diff --git a/cs/src/Ice/Ice.csproj b/cs/src/Ice/Ice.csproj index bc225e183e2..761a3a3f2f1 100755 --- a/cs/src/Ice/Ice.csproj +++ b/cs/src/Ice/Ice.csproj @@ -94,6 +94,11 @@ BuildAction = "Compile"
/>
<File
+ RelPath = "Assert.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "BasicInputStream.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/cs/src/Ice/Instance.cs b/cs/src/Ice/Instance.cs index f5095a9f0fe..b30d8062e31 100755 --- a/cs/src/Ice/Instance.cs +++ b/cs/src/Ice/Instance.cs @@ -440,27 +440,27 @@ namespace IceInternal } } +#if DEBUG ~Instance() { -#if DEBUG lock(this) { - Debug.Assert(_destroyed); - Debug.Assert(_referenceFactory == null); - Debug.Assert(_proxyFactory == null); - Debug.Assert(_outgoingConnectionFactory == null); - Debug.Assert(_connectionMonitor == null); - Debug.Assert(_servantFactoryManager == null); - Debug.Assert(_objectAdapterFactory == null); - Debug.Assert(_clientThreadPool == null); - Debug.Assert(_serverThreadPool == null); - Debug.Assert(_routerManager == null); - Debug.Assert(_locatorManager == null); - Debug.Assert(_endpointFactoryManager == null); - Debug.Assert(_pluginManager == null); - } -#endif DEBUG + IceUtil.Assert.FinalizerAssert(_destroyed); + IceUtil.Assert.FinalizerAssert(_referenceFactory == null); + IceUtil.Assert.FinalizerAssert(_proxyFactory == null); + IceUtil.Assert.FinalizerAssert(_outgoingConnectionFactory == null); + IceUtil.Assert.FinalizerAssert(_connectionMonitor == null); + IceUtil.Assert.FinalizerAssert(_servantFactoryManager == null); + IceUtil.Assert.FinalizerAssert(_objectAdapterFactory == null); + IceUtil.Assert.FinalizerAssert(_clientThreadPool == null); + IceUtil.Assert.FinalizerAssert(_serverThreadPool == null); + IceUtil.Assert.FinalizerAssert(_routerManager == null); + IceUtil.Assert.FinalizerAssert(_locatorManager == null); + IceUtil.Assert.FinalizerAssert(_endpointFactoryManager == null); + IceUtil.Assert.FinalizerAssert(_pluginManager == null); + } } +#endif public void finishSetup(ref string[] args) { diff --git a/cs/src/Ice/ObjectAdapterFactory.cs b/cs/src/Ice/ObjectAdapterFactory.cs index 4640cc8a7af..b3051e51772 100755 --- a/cs/src/Ice/ObjectAdapterFactory.cs +++ b/cs/src/Ice/ObjectAdapterFactory.cs @@ -165,18 +165,18 @@ namespace IceInternal _waitForShutdown = false; } +#if DEBUG ~ObjectAdapterFactory() { -#if DEBUG lock(this) { - Debug.Assert(_instance == null); - Debug.Assert(_communicator == null); - Debug.Assert(_adapters != null); - Debug.Assert(!_waitForShutdown); + IceUtil.Assert.FinalizerAssert(_instance == null); + IceUtil.Assert.FinalizerAssert(_communicator == null); + IceUtil.Assert.FinalizerAssert(_adapters != null); + IceUtil.Assert.FinalizerAssert(!_waitForShutdown); } -#endif DEBUG } +#endif private Instance _instance; private Ice.Communicator _communicator; diff --git a/cs/src/Ice/ObjectAdapterI.cs b/cs/src/Ice/ObjectAdapterI.cs index 3eb8c024c48..2c814341805 100755 --- a/cs/src/Ice/ObjectAdapterI.cs +++ b/cs/src/Ice/ObjectAdapterI.cs @@ -760,12 +760,12 @@ namespace Ice { lock(this) { - Debug.Assert(_threadPool == null); - Debug.Assert(_servantManager == null); - Debug.Assert(_communicator == null); - Debug.Assert(_incomingConnectionFactories != null); - Debug.Assert(_directCount == 0); - Debug.Assert(!_waitForDeactivate); + IceUtil.Assert.FinalizerAssert(_threadPool == null); + IceUtil.Assert.FinalizerAssert(_servantManager == null); + IceUtil.Assert.FinalizerAssert(_communicator == null); + IceUtil.Assert.FinalizerAssert(_incomingConnectionFactories != null); + IceUtil.Assert.FinalizerAssert(_directCount == 0); + IceUtil.Assert.FinalizerAssert(!_waitForDeactivate); } } diff --git a/cs/src/Ice/ServantManager.cs b/cs/src/Ice/ServantManager.cs index 3a8ef35d92c..eb73c0d6653 100755 --- a/cs/src/Ice/ServantManager.cs +++ b/cs/src/Ice/ServantManager.cs @@ -209,7 +209,7 @@ public sealed class ServantManager // //lock(this) //{ - //Debug.Assert(_instance == null); + //IceUtil.Assert.FinalizerAssert(_instance == null); //} } diff --git a/cs/src/Ice/TcpAcceptor.cs b/cs/src/Ice/TcpAcceptor.cs index ebf15fa064a..1e9779f9e14 100755 --- a/cs/src/Ice/TcpAcceptor.cs +++ b/cs/src/Ice/TcpAcceptor.cs @@ -118,15 +118,15 @@ namespace IceInternal } } +#if DEBUG ~TcpAcceptor() { -#if DEBUG lock(this) { - Debug.Assert(_fd == null); + IceUtil.Assert.FinalizerAssert(_fd == null); } -#endif DEBUG } +#endif private Instance _instance; private TraceLevels _traceLevels; diff --git a/cs/src/Ice/TcpTransceiver.cs b/cs/src/Ice/TcpTransceiver.cs index 8d778cdfa48..63d88bfd5a4 100755 --- a/cs/src/Ice/TcpTransceiver.cs +++ b/cs/src/Ice/TcpTransceiver.cs @@ -280,15 +280,15 @@ namespace IceInternal _desc = Network.fdToString(_fd); } +#if DEBUG ~TcpTransceiver() { -#if DEBUG lock(this) { - Debug.Assert(_fd == null); + IceUtil.Assert.FinalizerAssert(_fd == null); } -#endif DEBUG } +#endif private Socket _fd; private TraceLevels _traceLevels; diff --git a/cs/src/Ice/ThreadPool.cs b/cs/src/Ice/ThreadPool.cs index aaec1a1aa05..f7bacced0a2 100755 --- a/cs/src/Ice/ThreadPool.cs +++ b/cs/src/Ice/ThreadPool.cs @@ -108,14 +108,13 @@ namespace IceInternal } } +#if DEBUG ~ThreadPool() { -#if DEBUG lock(this) { - Debug.Assert(_destroyed); + IceUtil.Assert.FinalizerAssert(_destroyed); } -#endif DEBUG try { @@ -126,6 +125,7 @@ namespace IceInternal { } } +#endif public void destroy() { diff --git a/cs/src/Ice/UdpTransceiver.cs b/cs/src/Ice/UdpTransceiver.cs index 79e47209dce..8503c4b6cb6 100755 --- a/cs/src/Ice/UdpTransceiver.cs +++ b/cs/src/Ice/UdpTransceiver.cs @@ -440,15 +440,15 @@ namespace IceInternal } } +#if DEBUG ~UdpTransceiver() { -#if DEBUG lock(this) { - Debug.Assert(_fd == null); + IceUtil.Assert.FinalizerAssert(_fd == null); } -#endif DEBUG } +#endif private TraceLevels _traceLevels; private Ice.Logger _logger; |