C# 在Linux上从.NET内核手动调用recvmsg不会';不归
我正在为.NETCore编写一个DBus客户端。对于某些功能(例如systemd的抑制器锁),需要通过Unix套接字连接接收文件描述符,这些功能需要C# 在Linux上从.NET内核手动调用recvmsg不会';不归,c#,linux,sockets,.net-core,C#,Linux,Sockets,.net Core,我正在为.NETCore编写一个DBus客户端。对于某些功能(例如systemd的抑制器锁),需要通过Unix套接字连接接收文件描述符,这些功能需要recvmsg放入struct msghdr中的控件相关消息。NETs套接字API不允许我访问该函数(或抽象),所以我必须手动调用它 导致我第一次调用recvmsg的代码的核心是。当我在net462上编译它,并在我的Ubuntu16.04版或Yocto发行版(也使用Mono)上通过Mono 5.0.1运行它时,一切都按预期运行 当我根据netcore
recvmsg
放入struct msghdr
中的控件相关消息。NETs套接字API不允许我访问该函数(或抽象),所以我必须手动调用它
导致我第一次调用recvmsg的代码的核心是。当我在net462上编译它,并在我的Ubuntu16.04版或Yocto发行版(也使用Mono)上通过Mono 5.0.1运行它时,一切都按预期运行
当我根据netcoreapp1.1/netstandard1.6编译它并使用dotnet
运行它时,问题就开始了:针对org.freedesktop.DBus
的recvmsg
调用在第一次Hello
调用时不会返回
我可以通过dbus monitor--system
看到方法调用已经离开了我的应用程序,dbus发送了方法返回以及NameOwnerChanged
和nameaccessed
信号
几点注意:
- 对于我在Ubuntu上的测试,我已经将
和iovec
中的msghdr
字段从size\t
更改为int
,实际上是64位的(尽管它看起来像是结构所需的对齐方式使得它仍然可以工作)long
- 套接字上的实际
调用略有不同:对于net462,我从.NET Core 1.1复制了ConnectAsync
- 为了获得本机套接字句柄,我可以在net462上使用handle属性,但在netcoreapp1.1版本中
- 我还检查了.NETCore2.0Preview2版本,它们的行为与.NETCore1.1完全相同
- 在套接字上调用
而不是Read
是可行的,尽管内部读取只会映射到recvmsg
recvmsg
- 我比较了Mono和.NET Core在套接字上的公共属性,没有明显的区别:访问独占性使用在Mono上工作,但在.NET Core上抛出
- 在接收线程开始工作之前,会有一些身份验证代码。这会从套接字执行一些基于TPL的读取
缺少的环节是什么?连续出现了两个问题 首先,我的receive方法成功地吞并了一个异常,如果我运行了连接的Dispose方法,而不是从程序中按CTRL+C'ing,则该异常可能是可见的
System.TypeLoadException: Cannot marshal field 'control' of type 'msghdr': Unknown error.
at System.StubHelpers.ValueClassMarshaler.ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, CleanupWorkList& pCleanupWorkList)
at Dbus.Connection.recvmsg(IntPtr sockfd, msghdr& buf, Int32 flags)
at Dbus.Connection.receive()
因此,recvmsg
从未实际调用过。原因是键入了control
字段int[]
。我将其更改为int*
,并添加了另一个fixed
不过,奇怪的是,Mono能够用int[]
字段封送这个结构,而.NET核心却不能
在此之后,recvmsg
实际上被调用,但立即返回-1。不过,如果我只是使用.NET套接字阅读,一切都很好。我选择通过libcapi直接运行整个套接字处理,不再使用.NET核心套接字类型。现在,recvmsg
按预期工作。我假设我基于TPL的DBus授权离开套接字时有一个活动读取,我的receive方法正在执行第二个“阻塞”的读取,但我还没有验证这个假设