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