Nicolas Williams wrote:
On Wed, Aug 19, 2009 at 03:59:51PM -0400, Jeff Trawick wrote:
If an event is triggered at about the same time as a timeout expires, the port_getn() libc interface can return with

retcode: -1
errno: ETIME
number of events: updated to > 0

Sounds like the desired behavior.

The -1/ETIME must be ignored and the event(s) processed, as the kernel will not report it again until after a subsequent call to port_associate().

Sounds right.

First, thanks!

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).

I've seen it on 2009.06 and S10U7.

The man page has two descriptions for ETIME:

    The port_get() and port_getn() functions will fail if:
    ...
    ETIME     The time  interval  expired  before  the  expected
              number of events have been posted to the port.
    ...
    The port_getn() function will fail if:
    ...
    ETIME     The time  interval  expired  before  the  expected
              number  of  events  have  been  posted to the port
              (original value in nget), or nget is updated  with
              the  number of returned port_event_t structures in
              list[].

The second description of ETIME is perhaps unclear (is it "before A or B occurs" or "before A occurs; otherwise"); regardless, neither description mentions this behavior.

The wording in the manpage text that you quote is confusing, wrong even.
That ", or" should be " and" or ".  ".

ETIME is returned if the timer expires.  Regardless of whether ETIME
happens, *nget gets updated to the number of events returned (if neither ETIME
nor EINTR occur, and *nget <= max, then *nget will not be modified, of
course).

Think of ETIME/EINTR not as an error but as a supplementary bit of
inforation: port_getn() always returns, via the nget input/output
argument, the number of events fetched, and ETIME/EINTR merely indicate
whether a timeout or signal interrupted the wait for more events.

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?

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

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

A timeout or signal could occur before _any_ events occur, in which case
*nget will == 0.

Imagine an alternative port_getn() design where nget is not a pointer
and port_getn() returns the number of arguments fetched.  Ah, but to
avoid confusion you'd always have to first set errno = 0 _before calling
port_getn()_, and that'd be obnoxious.  Thus (I conjecture) the actual
design of port_getn().

I couldn't reproduce this behavior with port_get().

libevent handles/works around this behavior as follows (see the "errno == ETIME" path):

   if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
           &nevents, &ts)) == -1) {
       if (errno == EINTR) {
           evsignal_process();
           return (0);
       } else if (errno == ETIME) {
           if (nevents == 0)
               return (0);

This is correct, not a "workaround".  The returned events must get
processed.

       } else {
           perror("port_getn");
           return (-1);
       }

[...]

Can anyone advise on how an app can avoid pitfalls in this area regardless of *Solaris level?

Just like libevent does it.

Maybe ;)
I will open a bug at bugs.opensolaris.org to fix the code or the doc, unless for some reason shared here it isn't needed or there is a better way to resolve the issue.

That'd be great, thanks.
Will-do.

Thanks again!

_______________________________________________
networking-discuss mailing list
[email protected]

Reply via email to