protected virtual void Dispose(bool disposing) { const int ValidCloseResult = 0, MaxCloseAttemptCount = 5; // ensure that cleanup is only ever called once var socket = Interlocked.Exchange(ref _socket, NullSocket); if (socket != NullSocket) { int attemptCount = 0; while (true) { if (Interop.nn_close(socket) != ValidCloseResult) { int error = Interop.nn_errno(); // if we were interrupted by a signal, reattempt is allowed by the native library if (error == NanomsgSymbols.EINTR) { if (attemptCount++ >= MaxCloseAttemptCount) { if (disposing) { throw new NanomsgException("nn_close " + socket.ToString(), error); } else { // if we couldn't close the socket and we're on a finalizer thread, an exception would usually kill the process string errorText = string.Format("nn_close was repeatedly interrupted for socket {0}, which has not been successfully closed and may be leaked", socket); Trace.TraceError(errorText); Debug.Fail(errorText); return; } } else { // reattempt the close Thread.SpinWait(1); continue; } } else { Debug.Assert(error == NanomsgSymbols.EBADF); // currently the only non-interrupt errors are for invalid sockets, which can't be closed if (disposing) { throw new NanomsgException("nn_close " + socket.ToString(), error); } else { return; } } } else { break; } } } }
public static int Close(int s) { return(Interop.nn_close(s)); }