Hi

2011/5/4 Eric Wong <normalperson / yhbt.net>:
> KOSAKI Motohiro <kosaki.motohiro / gmail.com> wrote:
>> diff --git a/ext/-test-/wait_for_single_fd/wait_for_single_fd.c
>> b/ext/-test-/wait_for_single_fd/wait_for_single_fd.c
>> index d406724..6efd1af 100644
>> --- a/ext/-test-/wait_for_single_fd/wait_for_single_fd.c
>> +++ b/ext/-test-/wait_for_single_fd/wait_for_single_fd.c
>> @@ -25,6 +25,7 @@ Init_wait_for_single_fd(void)
>> =A0 =A0 =A0rb_define_const(rb_cObject, "RB_WAITFD_IN", INT2NUM(RB_WAITFD=
_IN));
>> =A0 =A0 =A0rb_define_const(rb_cObject, "RB_WAITFD_OUT", INT2NUM(RB_WAITF=
D_OUT));
>> =A0 =A0 =A0rb_define_const(rb_cObject, "RB_WAITFD_PRI", INT2NUM(RB_WAITF=
D_PRI));
>> + =A0 =A0rb_define_const(rb_cObject, "INT_MAX", INT2NUM(INT_MAX));
>> =A0 =A0 =A0rb_define_singleton_method(rb_cIO, "wait_for_single_fd",
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wait_for=
_single_fd, 3);
>>
>> Strongly disagree. Any language change should be passed matz review.
>
> Huh? =A0ext/-test-/* is only loaded during tests and never installed.
> No users see anything in ext/-test-/*

Oops, my bad. I misunderstood your diff. ok, I'll commit it.

>
>> 1) use ppoll(2) if available. and use INT_MAX if unavailable. or
>> 2) fallback select(2)
>>
>> 1) is safe because linux has ppol(2).
>
> OK, good point about ppoll(), I forgot that exists. =A0I'll work on that
> later or tomorrow.

ok.

>
>> =A0 =A0 =A0if (result > 0) {
>> - =A0 =A0 =A0 /* remain compatible with select(2)-based implementation *=
/
>> + =A0 =A0 =A0 /*
>> + =A0 =A0 =A0 =A0* Remain compatible with the select(2)-based implementa=
tion:
>> + =A0 =A0 =A0 =A0* 1) mask out poll()-only revents such as POLLHUP/POLLE=
RR
>> + =A0 =A0 =A0 =A0* 2) In case revents only consists of masked-out events=
, return all
>> + =A0 =A0 =A0 =A0* =A0 =A0requested events in the result and force the c=
aller to make an
>> + =A0 =A0 =A0 =A0* =A0 =A0extra syscall (e.g. read/write/send/recv) to g=
et the error.
>> + =A0 =A0 =A0 =A0*/
>> =A0 =A0 =A0 =A0 result =3D (int)(fds.revents & fds.events);
>> =A0 =A0 =A0 =A0 return result =3D=3D 0 ? events : result;
>> =A0 =A0 =A0}
>>
>> I don't understand this. Why does this behavior help to compatible?
>> When do we use it?
>
> We need to ensure rb_wait_for_single_fd(fd, events, timeval) returns
> only a subset of its +events+ argument because that's all select() is
> capable of.

Yes.

>
> If poll() returns POLLHUP/POLLERR, we should not expose those flags to
> callers of rb_wait_for_single_fd() since it would then behave
> differently if poll() or select() were used.
>
> =A0 =A0int events =3D RB_WAITFD_IN | RB_WAITFD_OUT;
> =A0 =A0int revents =3D rb_wait_for_single_fd(fd, events, NULL);
> =A0 =A0/* poll() itself may return POLLERR, but we prevent it from being =
in
> =A0 =A0 * revents since select() can't return that */
> =A0 =A0if (revents & RB_WAITFD_IN) {
> =A0 =A0 =A0 =A0/* since we don't know POLLERR, we fall back to fail here =
*/
> =A0 =A0 =A0 =A0if (read(fd, ...) < 0)
> =A0 =A0 =A0 =A0 =A0 =A0rb_sys_fail(0);
> =A0 =A0}
> =A0 =A0if (revents & RB_WAITFD_OUT) {
> =A0 =A0 =A0 =A0/* since we don't know POLLERR, we fall back to fail here =
*/
> =A0 =A0 =A0 =A0if (write(fd, ...) < 0)
> =A0 =A0 =A0 =A0 =A0 =A0rb_sys_fail(0);
> =A0 =A0}
> =A0 =A0/* user code shouldn't care about anything else since it only
> =A0 =A0 * requested RB_WAITFD_IN|RB_WAITFD_OUT */

Then, correct way is

/* copyed from linux */
#define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
#define POLLEX_SET (POLLPRI)

int revent_filter(int revents)
{
  int ret =3D 0;

  if (revents & POLLIN_SET)
        ret |=3D RB_WAITFD_IN;
  if (revents & POLLOUT_SET)
        ret |=3D RB_WAITFD_OUT;
  if (revents & POLLEX_SET)
        ret |=3D RB_WAITFD_PRI;
}

this code don't make false positive. I'll commit it.