How about this for passing file descriptors?

Corinna Vinschen
Mon Jul 15 01:31:00 GMT 2002

On Sat, Jul 13, 2002 at 03:46:37PM -0400, David Euresti wrote:
> Hello,
> 	I'm still thinking about this problem.  Since my first solution
> was shot down because of my use of the cygserver.

You got me wrong.  I appreciate your work and I'm not against inclusion
of your solution.  I just want *another* solution which works w/o the
cygserver.  In many cases a cygserver wouldn't be necessary and I still
like to have a running sshd which doesn't need cygserver.  If cygserver
is running, Cygwin could run your code.

> So here's a way to do it without the cygserver.  
> P1 wants to send FD1 to P2
> #1 P1 calls sendmsg with Data
> 	A.  Extract handle from FD1, H1.
> 	B.  Duplicate H1 -> H1bis
> 	C.  Create an Event E1
> 	D.  Create header as follows:
> 		HANDLE hDescriptor; = H1bis
> 		HANDLEINFO hi;  <--- This is obviously more.
> 		HANDLE HEvent;  = E1
> 		int Process;
> 	E.  Spawn a new thread to wait on event
> 		i.  When event is signalled close H1bis, then exit Thread.
> 	F.  Send header + Data
> #2 P2 calls recvmsg
> 	A.  Get header + Data
> 	B.  Duplicate HEvent into current process -> E2
> 	C.  Duplicate hDescriptor into current process -> H2
> 	D.  Call SetEvent on E2
> 	E.  Turn H2 and HANDLEINFO into FD2
> 	F.  Return data and FD2
> So this will work when the sender wants to close the FD after sending it.  
> Because a duplicate of the Handle is still hanging around in Duplicate 
> Handle.

I began to implement something like that the week before but it's far
from being finshed, mainly because of the problems to duplicate
different types of file handlers.  Each of them needs some different
strategy so I wonder if it makes sense to create a new virtual fhandler
method to do the job.  Anyway, what I'm implementing is the following:

- sendmsg() is called, type is AF_LOCAL.
- Count valid descriptors in msg_accrights.
- Create named shmem with header + room for count fhandlers.
- Create named event object
- The shmem gets a unique name.
- Fill shmem with header info (process id) and dup'd fhandlers.
- Create thread.
- Send shmem name over socket to receiver.
- Thread enters 'wait for event' state.

- recvmsg() is called, type is AF_LOCAL
- Read shmem name from socket.
- Open shmem, try OpenProcess(DUP_HANDLE) on sender process.
- If that works, duplicate HANDLEs (no details yet :-)), duplicate
  fhandlers and write '0' into the shmem header as own pid, close shmem.
- Otherwise write own pid into shmem.
- Pulse event object.
- If sucessful, continue recvmsg().
- Otherwise enter 'wait for event' state.

- Wake up.
- If shmem header does *not* contain '0' as receiver pid:
  - Try OpenProcess(DUP_HANDLE) on receiver pid.
  - If that works, duplicate HANDLEs and write '0' into shmem header
    as own pid.
  - Otherwise report error.
  - Close shmem.
  - Pulse event object.
- Otherwise close HANDLEs, close shmem.
- Terminate thread.
- Continue.

- Wake up.
- If no error, duplicate fhandlers.
- Close shmem.
- Continue.

What I completely ignored so far is how and when to call your cygserver
code instead of the above.  Are you interested in working on that code,
too?  I'd send you my diffs so far and we definitely need to discuss
this and that.

> It will not work if the sender exits after sending it.  Or rather there 
> will be a race condition.  Is there a way to keep the process alive for a 
> little while?  At least like 10 seconds or until the Event is signalled?

I didn't think of that but I think that's a minor point.  We can
solve that in a later state, isn't it?


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                      
Red Hat, Inc.

More information about the Cygwin-developers mailing list