我正在为.NET Core here编写一个DBus客户端。对于某些功能(例如systemd的抑制器锁定),需要通过Unix套接字连接接收文件描述符,并且需要recvmsg
放在struct msghdr
中的与控件相关的消息。 .NETs套接字API不允许我访问该函数(或抽象),因此我必须手动调用它。
导致我第一次recvmsg
来电的代码的内容是here。当我针对net462编译并在我的Ubuntu 16.04盒子或Yocto发行版(也使用Mono)上通过Mono 5.0.1运行它时,一切都按预期工作。
当我针对netcoreapp1.1 / netstandard1.6对其进行编译并使用dotnet
运行时,问题就开始了:recvmsg
调用只是在第一次Hello
调用时没有返回org.freedesktop.DBus
。
我可以看到dbus-monitor --system
方法调用已离开我的应用程序,并且DBus发送了方法返回以及NameOwnerChanged
和NameAcquired
信号。
几点说明:
size_t
和iovec
中的msghdr
字段从int
更改为long
,实际上是64位(虽然它看起来像结构所需的对齐使它无论如何都可以工作)ConnectAsync
调用略有不同:对于net462,我从.NET Core 1.1复制了extension method Read
上调用recvmsg
可以正常工作,尽管Read内部只是映射到recvmsg
我试图浏览CoreFX套接字代码,但由于涉及的复杂性,这并不是很有趣。
缺少什么链接?
答案 0 :(得分:1)
有两个连续的问题。
首先,我的receive方法成功地吞下了一个异常,如果我已经运行了Connection的Dispose方法而不是CTRL + C,那么该异常就可见了。
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 Core不是。
之后,实际调用recvmsg
,但立即返回-1。不过,如果我只是Read
使用.NET套接字,一切都运行正常。我选择直接通过libc API运行整个套接字处理,不再使用.NET Core Socket类型。现在,recvmsg
按预期工作。我假设我的基于TPL的DBus授权让套接字有一个有效读取,我的接收方法正在执行第二次读取被阻止"但我还没有验证这个假设。 / p>