hurd-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

io_close proposal


From: Marcus Brinkmann
Subject: io_close proposal
Date: Thu, 16 May 2002 00:23:12 +0200
User-agent: Mutt/1.3.28i

Hi,

we have at least three cases where we need synchronization with the server
at close() time:

* closing the read end of a pipe, writing to it after that must fail
  (bites perl test)
* closing a socket with SO_LINGER option set, should block until timeout and
  then return meaningful error value
* record locking: any close on a file descriptor (even a dup'ed one) should
  release all locks.

They are all different, but should fit into a single RPC at close.
What I have in mind is a close like call to give up a send right (the
description is a bit weird, please apply common sense in its interpretation):

/* Release the send right IORIGHT.  If this was the last send
   right to IO_OBJECT, a server-specific behaviour is applied.
   A pipe server will only return when the end of the pipe is closed.
   A socket server might return EWOULDBLOCK if the SO_LINGER
   option is used and there are pending packets after the timeout.

   A server supporting the record locking protocol will also
   release all locks associated with IO_OBJECT.  */
routine io_close (
        io_object: io_t;
        RPT
        ioright: mach_port_send_t);
 
I have already tested that if this is invoked like this:

io_close (port, port, MACH_MSG_TYPE_MOVE_SEND);

then the send right will be correctly moved in the message, and the server
can deallocate it, and possibly synchronzie, here some pseudo code:

/* Implement io_close as described in <hurd/io.defs>. */
kern_return_t
trivfs_S_io_close (struct trivfs_protid *cred,
                   mach_port_t reply, mach_msg_type_name_t reply_type,
                   mach_port_t ioport)
{
  mach_port_status_t st;
  error_t err;

  if (!cred)
    return EOPNOTSUPP;
  mach_port_deallocate (mach_task_self (), ioport);
  /* Now for example: */
  if (WE DO RECORD LOCKING)
    RELEASE LOCKS;

  if (THIS IS A PIPE, OR A SOCKET)
    {
      err = mach_port_get_receive_status (ioport, &st);
      if (!err && !st.mps_srights)
        {
          /* This was the last send right.  */
          SYNCHRONIZE WITH NO SENDERS NOTIFICATIONS, OR SIMILAR.
        }
    }

  return err;
}

This is all tested.  It does indeed what I expected it to do.  The receive
port in the server will have 1 send once right and no send right after the
mach_port_deallocate, if this was the last sender.  I am not sure where the
send-once right comes from, but I think it is the send-once right for the no
senders notification.

This seems to solve some problems with pipes, sockets and record locking.
The plan is to implement the various synchronization requirements on the
server side, and to call io_close in the glibc close() function, instead
the mach_port_deallocate.

One problem is definitive interruption.  We can not move the send right in
the caller and be interruption safe.  I don't know yet what requirements we
there are in the case where close() is interrupted, so I am not sure how
much this is an issue (beside the problem that all io_* calls get
interruption handled in the stub code).

Thanks,
Marcus

-- 
`Rhubarb is no Egyptian god.' Debian http://www.debian.org address@hidden
Marcus Brinkmann              GNU    http://www.gnu.org    address@hidden
address@hidden
http://www.marcus-brinkmann.de



reply via email to

[Prev in Thread] Current Thread [Next in Thread]