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]