On Wed, Aug 19, 2009 at 05:19:40PM -0400, Jeff Trawick wrote:
> First, thanks!

NP.

> A lot of other people can't code correctly to this type of interface. 
> Even Sun examples can be wrong 
> (http://developers.sun.com/solaris/articles/listing2_poll.c).

Ooops!  :)

> Can you confirm that ETIME and EINTR are the only two -1/errno 
> indications that can be reported at the same time that one or more 
> events is returned?

Hmmm, from code inspection I see that the actual port_event_t list[]
entries are copied out in one go when port_getn() returns (see
uts/common/fs/portfs/port.c:port_getn() around lines 1524-1527 and
1561-1562).  There'd be no point in trying to validate the list[]
argument any earlier than that.  The copyout() can fail, resulting in
EFAULT, but the events have been consumed anyways, and *nget still gets
updated though you obviously lose some of them.

You can get EFAULT if part or all of the list[] array fall outside
mapped address space.  Don't do that :)

EBADFD can result if the port is closed at any time while port_getn() is
not done getting events, in which case port_getn() can have consumed
some events, list[] and *nget are updated.

EBADF and EINVAL can only result _before_ consuming any events (EINVAL
occurs if max and *nget conflict, or if the timeout is invalid, because,
e.g., it has too many nanoseconds).

> Alternatively, can you state categorically that if an event is returned, 
> no errors (EBADF, EBADFD, EFAULT, etc.) occurred?

No.  See above.

> I'd like to fix my code and not worry about some other errno having a 
> similar issue in the future.

        saved_errno = 0;
        res = port_getn(port, pevlist, max, &nevents, &timeout);
        if (res == -1) {
                switch (errno) {
                case EINVAL:
                        /* shouldn't happen; fatal? */
                        ...
                case EBADF:
                        /* port got closed, no events consumed; bail? */
                        ...
                case EFAULT:
                        /* something really bad happened; exit? */
                        ...
                }
        }
        /* If we get here errno == 0, EBADFD, EINTR or ETIME */
        saved_errno = errno;
        if (nevents >= 0) {
                /* handle events returned by port_getn() */
                ...
        }
        switch (saved_errno) {
        case ETIME:
                /* handle timeout */
                ...
        case EINTR:
                /* handle interrupt, probably just ignore */
                ...
        case EBADFD:
                /* oops!  port got closed!  bail, re-open, ... */
                ...
        }

> >Just like libevent does it.
> 
> Maybe ;)

Yes, one can do something a bit more involved (see above).

Nico
-- 
_______________________________________________
networking-discuss mailing list
[email protected]

Reply via email to