[Top][All Lists]

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

Re: io_close proposal

From: Marcus Brinkmann
Subject: Re: io_close proposal
Date: Wed, 16 Oct 2002 19:51:13 +0200
User-agent: Mutt/1.4i

On Thu, May 16, 2002 at 04:29:49PM -0400, Roland McGrath wrote:
> > The way I read POSIX, we are not even allowed to restart the operation,
> > but we must (POSIX says "shall") return -1/EINTR.  But I only checked
> > the definition of close() so far, not if SA_RESTART overrides this.
> I think you are probably right about this.  The question is whether, if the
> appropriate synchronization has not happened, we are required to leave the
> descriptor open (as if close had never been called).  Depending on exactly
> what "unspecified" means here, an application might be justified in
> diagnosing the EINTR failure and then using the descriptor again (perhaps
> in calls other than just retrying the close) and expect either EBADF with
> an implied guarantee of appropriate synchronization e.g. with the other end
> of the pipe, or behavior exactly as if the close call had never been made,
> and nothing in between.

I think I was wrong about it.  I think that SA_RESTART applies globally to
all functions that can return EINTR:

SA_RESTART      This flag affects the behavior of interruptible functions;
                that is, those specified to fail with errno set to [EINTR].
                If set, and a function specified as interruptible is
                interrupted by this signal, the function shall restart and
                shall not fail with [EINTR] unless otherwise specified. If
                the flag is not set, interruptible functions interrupted by
                this signal shall fail with errno set to [EINTR].

Except for pselect() and select, which explicitely says:

If SA_RESTART has been set for the interrupting signal, it is
implementation-defined whether the function restarts or returns with [EINTR].

So, in my opinion, the question is quite the other way round:  It is clear
that if SA_RESTART is not set, and close() is interrupted, the state of the
file descriptor is unspecified.  Unspecified is like implementation-defined,
except that we don't need to document how our implementation behaves (the
other option is undefined, which means any program that calls close() while
it might receive an interrupting signal is invalid! and trigger any weird
behaviour).  I think we are relieved from fulfilling any guarantees.

However, what if SA_RESTART is set.  Then we have to retry a failed close. 
But what can we return when retrying it?  I think we should return EBADF
immediately (it's just as if you retry manually, as the filedescriptor
became invalid).

So the table would look like this:

The entries are in the form: return value, fd state (DEALLOC or OPEN),
synchronization requirements guaranteed (Y or N). "-" means unspecified.
I am just guessing the Unix behaviour, this would require more testing.

                                POSIX.1         Unix            The Hurd
close() succeeds                0,DEALLOC,Y     0,DEALLOC,Y     0,DEALLOC,Y
!SA_RESTART, interrupted        EINTR,-,-       EINTR,OPEN?,N?  EINTR,DEALLOC,N
SA_RESTART, interrupted         !EINTR,?,?      0,DEALLOC,Y?    EBADF,DEALLOC,N

A bit too many ?s here for my taste, but it doesn't seem terribly wrong. 
The EBADF in the Hurd with SA_RESTART is a bit ugly, but I think it would be
wrong to return 0 if the synchronization requirements are not met.  Mmmh.

As for the test in the real world, I guess that nobody checks the return
value of close(), except maybe for SO_LINGER.  And then application
programmers can only guarantee _specified_ behaviour by disabling
interrupting signals before doing that.  POSIX.1 is silent about what
should happen in the SA_RESTART case except that the close is "restarted"
whatever that means for close, and that EINTR is not returned.  Restarting
close on a filedesriptor with unspecified state has unspecified outcome in
my book.  For my proposed io_close solution it would at least be implementation
defined (because we always go into the asynchronous close when interrupted).

I don't think there is much to worry about by going that way.  I have to
admit feeling uncomfortable about not being able to properly restart a
close.  But otoh, implementing a restartable close() on the server side
would only be meaningful for SO_LINGER (which is the only blocking close we
have anyway, really), and trying to figure that out only adds more hair
(like what should happen if you interrupt the close jsut before the linger
time ends and restart right after?  Or what should happen at all when the
linger time is interrupted).

Yeah.  Every other close operations (pipe close, file close with record
locks) doesn't really block for a long time.  We probably should be able to
implement them without waiting on a condition etc.  So they will not return
EINTR anyway, but just succeed quickly.


`Rhubarb is no Egyptian god.' GNU    address@hidden
Marcus Brinkmann              The Hurd

reply via email to

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