AF_UNIX status report
Ken Brown
kbrown@cornell.edu
Thu Nov 5 14:23:34 GMT 2020
On 11/4/2020 7:03 AM, Corinna Vinschen wrote:
> On Nov 3 10:43, Ken Brown via Cygwin-developers wrote:
>> On 10/30/2020 5:20 AM, Corinna Vinschen wrote:
>>> On Oct 29 14:53, Joe Lowe wrote:
>>>> On 2020-10-29 13:19, Ken Brown via Cygwin-developers wrote:
>>>>> On 10/27/2020 5:43 AM, Corinna Vinschen wrote:
>>>>>> On Oct 26 18:04, Ken Brown via Cygwin-developers wrote:
>>>>>>> 2. I haven't given any thought at all as to how to implement SCM_RIGHTS
>>>>>>> ancillary data. I could definitely use suggestions on that
>>>>>>> before I start
>>>>>>> thrashing around.
>>>>>>
>>>>>> I have only vague ideas at that point. Assuming we can replace the
>>>>>> socket implemantation with the pipe implementation, what we have is a
>>>>>> pipe which can impersonate the peer at least from the server side, and
>>>>>> it knows the client process. This in turn can be used to duplicate
>>>>>> handles. So what we could do is to define fhandler methods which create
>>>>>> a matching serialization and deserialization of the fhandler data, plus
>>>>>> duplicating the handles for the other process, sent over the pipe as
>>>>>> admin package. This must work in either direction, regardless if the
>>>>>> server or the client sends the SCM_RIGHTS block.
>>>>>
>>>>> This sounds reasonable.
>>>>>
>>>>> I have no experience with serialization. Do you happen to know of a
>>>>> good example that I could look at?
>>>
>>> Unfortunately not. Probably we can just send the entire fhandler and
>>> the recipient fiddles the content in a per-class way, kind of like
>>> fhandler::dup.
>>
>> I'm working on implementing this, and I've bumped into an elementary C++
>> question. In order to send the fhandler in an admin packet, I need to
>> determine its size dynamically, given an (fhandler_base *) pointer to it.
>> AFAICS, this requires something like the following.
>>
>> In the definition of class fhandler_base, put a virtual function
>>
>> virtual size_t size () const { return sizeof *this; }
>>
>> and then repeat this essentially verbatim in every derived class:
>>
>> size_t size () const { return sizeof *this; }
>>
>> Does this seem right? I did an internet search and didn't find anything
>> substantially different, although there were several suggestions to use
>> templates in various ways. I'm not convinced that using templates would
>> actually improve the code, but I can do it if you think it's better.
>
> Actually, I don't like templates that much. You could do the above, or
> just always send a block of size fhandler_union.
OK, here's how I imagine this working:
A process wants to send a file descriptor fd, so it creates a msghdr with an
SCM_RIGHTS cmsghdr and calls sendmsg. The latter creates and sends an admin
packet A containing the fhandler for fd, and then it sends the original packet P.
At the receiving end, recvmsg sees packet A first (recvmsg is always checking
for admin packets anyway whenever it's called). It stores the fhandler
somewhere. When it then reads packet P, it retrieves the stored fhandler,
fiddles with it (duplicating handles, etc.), and creates the new file descriptor.
Does this seem reasonable? The main thing bothering me is the lack of
atomicity. I don't like the gap between the sending of the two packets A and P,
and similarly for the receiving. I thought about using the io_lock to at least
make sure that the two packets are adjacent in the pipe, but I don't know if we
want to tie up the io_lock for that long.
Also, the sending process might be sending several file descriptors at once, so
that there would be several admin packets to be sent (unless we want to cram it
all into one).
Ken
More information about the Cygwin-developers
mailing list