Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TEST] Ctor_Dispose_HandleClosedIfOwnsHandle #73168

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ public void Ctor_SafeHandle_Invalid_ThrowsException()
[PlatformSpecific(TestPlatforms.Linux)]
public void Ctor_Socket_FromPipeHandle_Ctor_Dispose_Success(bool ownsHandle)
{
(int fd1, int fd2) = pipe2();
close(fd2);
(int fd1, int fd2) = LibcInterop.pipe2();
LibcInterop.close(fd2);

using var _ = new Socket(new SafeSocketHandle(new IntPtr(fd1), ownsHandle));
}
Expand Down Expand Up @@ -631,28 +631,30 @@ public unsafe void Ctor_SafeHandle_UnknownSocket_Success()
}
}

private static class LibcInterop
{
[DllImport("libc")]
public static unsafe extern int socketpair(int domain, int type, int protocol, int* ptr);

[DllImport("libc")]
private static unsafe extern int socketpair(int domain, int type, int protocol, int* ptr);

[DllImport("libc")]
private static extern int close(int fd);
[DllImport("libc")]
public static extern int close(int fd);

[DllImport("libc", SetLastError = true)]
private static unsafe extern int pipe2(int* pipefd, int flags);
[DllImport("libc", SetLastError = true)]
public static unsafe extern int pipe2(int* pipefd, int flags);

private static unsafe (int, int) pipe2(int flags = 0)
{
Span<int> pipefd = stackalloc int[2];
fixed (int* ptr = pipefd)
public static unsafe (int, int) pipe2(int flags = 0)
{
if (pipe2(ptr, flags) == 0)
Span<int> pipefd = stackalloc int[2];
fixed (int* ptr = pipefd)
{
return (pipefd[0], pipefd[1]);
}
else
{
throw new Win32Exception();
if (pipe2(ptr, flags) == 0)
{
return (pipefd[0], pipefd[1]);
}
else
{
throw new Win32Exception();
}
}
}
}
Expand All @@ -669,7 +671,7 @@ public unsafe void Ctor_SafeHandle_SocketPair_Success()

fixed (int* bufferPtr = ptr)
{
int result = socketpair(AF_UNIX, SOCK_STREAM, 0, bufferPtr);
int result = LibcInterop.socketpair(AF_UNIX, SOCK_STREAM, 0, bufferPtr);
Assert.Equal(0, result);
}

Expand All @@ -684,8 +686,33 @@ public unsafe void Ctor_SafeHandle_SocketPair_Success()
Assert.Equal(ProtocolType.Unspecified, s.ProtocolType);
}

close(ptr[0]);
close(ptr[1]);
LibcInterop.close(ptr[0]);
LibcInterop.close(ptr[1]);
}

[Theory]
[PlatformSpecific(TestPlatforms.Windows)] // Closing socket handle manually has side-effects in Unix SocketAsyncEngine.
[InlineData(false)]
[InlineData(true)]
public void Ctor_Dispose_HandleClosedIfOwnsHandle(bool ownsHandle)
{
Socket original = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IntPtr handleValue = original.Handle;

SafeSocketHandle handleClone = new SafeSocketHandle(handleValue, ownsHandle: ownsHandle);
Socket socketClone = new Socket(handleClone);
socketClone.Dispose();

bool manualCloseSucceeded = closesocket(handleValue) == 0;
Assert.Equal(!ownsHandle, manualCloseSucceeded);

#if DEBUG // The finalizer will fail to close the handle which leads to an assertion failure in Debug builds.
GC.SuppressFinalize(original);
GC.SuppressFinalize(original.SafeHandle);
#endif

[DllImport("ws2_32.dll", SetLastError = true)]
static extern int closesocket(IntPtr socketHandle);
}

private static void AssertEqualOrSameException<T>(Func<T> expected, Func<T> actual)
Expand Down