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]