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.

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

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.

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

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

Reply via email to