public static unsafe SocketError GetLingerOption(SafeCloseSocket handle, out LingerOption optionValue) { var linger = new Interop.libc.linger(); var optLen = (uint)sizeof(Interop.libc.linger); int err = Interop.libc.getsockopt(handle.FileDescriptor, Interop.libc.SOL_SOCKET, Interop.libc.SO_LINGER, &linger, &optLen); if (err == -1) { optionValue = default(LingerOption); return GetLastSocketError(); } optionValue = new LingerOption(linger.l_onoff != 0, linger.l_linger); return SocketError.Success; }
private unsafe SocketError InnerReleaseHandle() { int errorCode; if (_asyncContext != null) { _asyncContext.Close(); } // If _blockable was set in BlockingRelease, it's safe to block here, which means // we can honor the linger options set on the socket. It also means closesocket() might return WSAEWOULDBLOCK, in which // case we need to do some recovery. if (_blockable) { GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") Following 'blockable' branch."); errorCode = Interop.Sys.Close((int)handle); if (errorCode == -1) { errorCode = (int)Interop.Sys.GetLastError(); } GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") close()#1:" + errorCode.ToString()); #if DEBUG _closeSocketHandle = handle; _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif // If it's not EWOULDBLOCK, there's no more recourse - we either succeeded or failed. if (errorCode != (int)Interop.Error.EWOULDBLOCK) { if (errorCode == 0 && _asyncContext != null) { _asyncContext.Close(); } return SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); } // The socket must be non-blocking with a linger timeout set. // We have to set the socket to blocking. errorCode = Interop.Sys.Fcntl.SetIsNonBlocking((int)handle, 0); if (errorCode == 0) { // The socket successfully made blocking; retry the close(). errorCode = Interop.Sys.Close((int)handle); GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") close()#2:" + errorCode.ToString()); #if DEBUG _closeSocketHandle = handle; _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif if (errorCode == 0 && _asyncContext != null) { _asyncContext.Close(); } return SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); } // The socket could not be made blocking; fall through to the regular abortive close. } // By default or if CloseAsIs() path failed, set linger timeout to zero to get an abortive close (RST). var linger = new Interop.libc.linger { l_onoff = 1, l_linger = 0 }; errorCode = Interop.libc.setsockopt((int)handle, Interop.libc.SOL_SOCKET, Interop.libc.SO_LINGER, &linger, (uint)sizeof(Interop.libc.linger)); #if DEBUG _closeSocketLinger = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif if (errorCode == -1) { errorCode = (int)Interop.Sys.GetLastError(); } GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") setsockopt():" + errorCode.ToString()); if (errorCode != 0 && errorCode != (int)Interop.Error.EINVAL && errorCode != (int)Interop.Error.ENOPROTOOPT) { // Too dangerous to try closesocket() - it might block! return SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); } errorCode = Interop.Sys.Close((int)handle); #if DEBUG _closeSocketHandle = handle; _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") close#3():" + (errorCode == -1 ? (int)Interop.Sys.GetLastError() : errorCode).ToString()); return SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); }
public static unsafe SocketError SetLingerOption(SafeCloseSocket handle, LingerOption optionValue) { var linger = new Interop.libc.linger { l_onoff = optionValue.Enabled ? 1 : 0, l_linger = optionValue.LingerTime }; int err = Interop.libc.setsockopt(handle.FileDescriptor, Interop.libc.SOL_SOCKET, Interop.libc.SO_LINGER, &linger, (uint)sizeof(Interop.libc.linger)); return err == -1 ? GetLastSocketError() : SocketError.Success; }
private unsafe SocketError InnerReleaseHandle() { int errorCode; if (_asyncContext != null) { _asyncContext.Close(); } // If _blockable was set in BlockingRelease, it's safe to block here, which means // we can honor the linger options set on the socket. It also means closesocket() might return WSAEWOULDBLOCK, in which // case we need to do some recovery. if (_blockable) { GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") Following 'blockable' branch."); errorCode = Interop.Sys.Close((int)handle); if (errorCode == -1) { errorCode = (int)Interop.Sys.GetLastError(); } GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") close()#1:" + errorCode.ToString()); #if DEBUG _closeSocketHandle = handle; _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif // If it's not EWOULDBLOCK, there's no more recourse - we either succeeded or failed. if (errorCode != (int)Interop.Error.EWOULDBLOCK) { if (errorCode == 0 && _asyncContext != null) { _asyncContext.Close(); } return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode)); } // The socket must be non-blocking with a linger timeout set. // We have to set the socket to blocking. errorCode = Interop.Sys.Fcntl.SetIsNonBlocking((int)handle, 0); if (errorCode == 0) { // The socket successfully made blocking; retry the close(). errorCode = Interop.Sys.Close((int)handle); GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") close()#2:" + errorCode.ToString()); #if DEBUG _closeSocketHandle = handle; _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif if (errorCode == 0 && _asyncContext != null) { _asyncContext.Close(); } return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode)); } // The socket could not be made blocking; fall through to the regular abortive close. } // By default or if CloseAsIs() path failed, set linger timeout to zero to get an abortive close (RST). var linger = new Interop.libc.linger { l_onoff = 1, l_linger = 0 }; errorCode = Interop.libc.setsockopt((int)handle, Interop.libc.SOL_SOCKET, Interop.libc.SO_LINGER, &linger, (uint)sizeof(Interop.libc.linger)); #if DEBUG _closeSocketLinger = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif if (errorCode == -1) { errorCode = (int)Interop.Sys.GetLastError(); } GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") setsockopt():" + errorCode.ToString()); if (errorCode != 0 && errorCode != (int)Interop.Error.EINVAL && errorCode != (int)Interop.Error.ENOPROTOOPT) { // Too dangerous to try closesocket() - it might block! return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode)); } errorCode = Interop.Sys.Close((int)handle); #if DEBUG _closeSocketHandle = handle; _closeSocketResult = SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode); #endif GlobalLog.Print("SafeCloseSocket::ReleaseHandle(handle:" + handle.ToString("x") + ") close#3():" + (errorCode == -1 ? (int)Interop.Sys.GetLastError() : errorCode).ToString()); return(SocketPal.GetSocketErrorForErrorCode((Interop.Error)errorCode)); }