As of #80715, many System.Net.Sockets.Tests test fail with the error:
System.Exception : Failed to create the 'shadow' (port blocker) socket in 16 attempts.
Looking at the behavior with strace shows the error is caused by failed attempts to bind to file descriptor 0 (which is of course not a socket):
[pid 774258] bind(0, {sa_family=AF_INET6, sin6_port=htons(44087), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_scope_id=0}, 28) = -1 ENOTSOCK (Socket operation on non-socket)
Investigating this closer shows that the bind call happens via a P/Invoke in the new test infrastructure:
| [Runtime.InteropServices.DllImport("libc",SetLastError=true)] |
| staticexternintbind(SafeSocketHandlesocket,IntPtrsocketAddress,uintaddrLen); |
This seems to trigger marshalling code in Mono that accesses the IntPtr wrapped by the SafeHandle:
| /* Pull the handle field from SafeHandle */ |
| cb_to_mono->methodBuilder.emit_ldarg (mb, argnum); |
| cb_to_mono->methodBuilder.emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle)); |
| cb_to_mono->methodBuilder.emit_byte (mb, CEE_LDIND_I); |
| cb_to_mono->methodBuilder.emit_stloc (mb, conv_arg); |
using the data structure here:
| /* |
| * The definition of the first field in SafeHandle, |
| * Keep in sync with SafeHandle.cs, this is only used |
| * to access the `handle' parameter. |
| */ |
| typedefstruct { |
| MonoObject base; |
| void *handle; |
| } MonoSafeHandle; |
However, as of #71991 the definition of the SafeHandle type on the managed side is:
| // IMPORTANT: |
| // - Do not add or rearrange fields as the EE depends on this layout, |
| // as well as on the values of the StateBits flags. |
| // - The EE may also perform the same operations using equivalent native |
| // code, so this managed code must not assume it is the only code |
| // manipulating _state. |
| |
| #if DEBUG |
| privatereadonlystring?_ctorStackTrace; |
| #endif |
| /// <summary>Specifies the handle to be wrapped.</summary> |
| protectedIntPtrhandle; |
Note when the library is built for the Debug configuration, the layout no longer matches - in the place Mono expects the
handle field, we now have the
_ctorStackTrace field. As this is usually null, we get 0 as file descriptor ...
@stephentoub I see you updated the matching CoreCLR definition with #71991, but not the Mono definition. I guess this should be done there as well - however I'm not clear how to do this only for the Debug version of the library, this is something the Mono runtime doesn't currently appear to be doing ...
Also, I was quite confused why this problem only shows up in this one test, and not for all the "normal" places in the library where SafeHandles are marshalled to native code. I now see this is using a different mechanism:
| [LibraryImport(Libraries.SystemNative,EntryPoint="SystemNative_Bind")] |
| internalstaticunsafepartialErrorBind(SafeHandlesocket,ProtocolTypesocketProtocolType,byte*socketAddress,intsocketAddressLen); |
which doesn't trigger the Mono marshalling code, but generates IL that uses calls to
System.Runtime.InteropServices.SafeHandle:DangerousGetHandle instead of accessing the handle at a hard-coded offset.
CC @antonfirsov@vargaz@omajid@tmds
As of #80715, many
System.Net.Sockets.Teststest fail with the error:Looking at the behavior with strace shows the error is caused by failed attempts to bind to file descriptor 0 (which is of course not a socket):
Investigating this closer shows that the bind call happens via a P/Invoke in the new test infrastructure:
runtime/src/libraries/Common/tests/System/Net/Sockets/SocketTestExtensions.cs
Lines 205 to 206 in 65f5ad0
This seems to trigger marshalling code in Mono that accesses the
IntPtrwrapped by theSafeHandle:runtime/src/mono/mono/component/marshal-ilgen.c
Lines 1919 to 1923 in 65f5ad0
using the data structure here:
runtime/src/mono/mono/metadata/class-internals.h
Lines 670 to 678 in 65f5ad0
However, as of #71991 the definition of the
SafeHandletype on the managed side is:runtime/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeHandle.cs
Lines 24 to 35 in 65f5ad0
Note when the library is built for the Debug configuration, the layout no longer matches - in the place Mono expects the
handlefield, we now have the_ctorStackTracefield. As this is usually null, we get 0 as file descriptor ...@stephentoub I see you updated the matching CoreCLR definition with #71991, but not the Mono definition. I guess this should be done there as well - however I'm not clear how to do this only for the Debug version of the library, this is something the Mono runtime doesn't currently appear to be doing ...
Also, I was quite confused why this problem only shows up in this one test, and not for all the "normal" places in the library where
SafeHandlesare marshalled to native code. I now see this is using a different mechanism:runtime/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Bind.cs
Lines 12 to 13 in 65f5ad0
which doesn't trigger the Mono marshalling code, but generates IL that uses calls to
System.Runtime.InteropServices.SafeHandle:DangerousGetHandleinstead of accessing the handle at a hard-coded offset.CC @antonfirsov@vargaz@omajid@tmds