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]
