problem with poll_poll() under FreeBSD

Zajcev Evgeny lg.zevlg at gmail.com
Mon Mar 29 09:56:58 CEST 2010


Marc Lehmann <schmorp at schmorp.de> writes:

> On Fri, Mar 26, 2010 at 10:44:31AM +0300, Zajcev Evgeny <lg.zevlg at gmail.com> wrote:
>> aha, i will investigate futher and report.  i've heard from others
>> they have glitches with FreeBSD's poll too
>
> I vaguely think this has been reported before, but we never found any
> details (it does work on my freebsd vmwares).
>
> If you find out more details, please let us know. In any case, this is
> likely a quetsion for the kernel team - if you have deifnite knowledge
> (res == 2, but only one nonzero revents) then you have a very good
> case.

ok, here is the update:

i've added 

  int nres = res;
  struct pollfd* npolls = polls;
  int npcnt = pollcnt;

bellow the call to poll() in poll_poll() to keep track of initial
values, after that i've examined core:

(gdb) bt
#0  0x080907f6 in fd_kill (loop=0x80d1560, fd=1953719670) at ev.c:827
#1  0x080912c7 in poll_poll (loop=0x80d1560, timeout=14.953731828951277)
    at ev_poll.c:114
#2  0x0809327d in ev_loop (loop=0x80d1560, flags=0) at ev.c:2108
...
(gdb) up
#1  0x080912c7 in poll_poll (loop=0x80d1560, timeout=14.953731828951277)
    at ev_poll.c:114
114                 fd_kill (EV_A_ p->fd);
(gdb) p nres
$1 = 2
(gdb) p npolls[0]
$2 = {fd = 3, events = 1, revents = 0}
(gdb) p npolls[1]
$3 = {fd = 6, events = 5, revents = 4}
(gdb) p npolls[2]
$4 = {fd = 5, events = 1, revents = 0}
(gdb) p npolls[3]
$5 = {fd = 1953719670, events = 11625, revents = 28020}
(gdb) p npcnt
$6 = 3
(gdb) 

as it was predicted, FreeBSD's poll() returned incorrect value :(.
I've skimed poll() implementation in FreeBSD and did not found any
place that can give such results, it might be due to lack of
knowledge.  I'll try to contact freebsd community..

the only thing i can think right now is simple workaround:

--- a/libev/ev_poll.c
+++ b/libev/ev_poll.c
@@ -90,6 +90,7 @@ poll_poll (EV_P_ ev_tstamp timeout)
 {
   struct pollfd *p;
   int res = poll (polls, pollcnt, (int)ceil (timeout * 1000.));
+  int npcnt = pollcnt;
 
   if (expect_false (res < 0))
     {
@@ -101,11 +102,9 @@ poll_poll (EV_P_ ev_tstamp timeout)
         ev_syserr ("(libev) poll");
     }
   else
-    for (p = polls; res; ++p)
+    for (p = polls; res && npcnt--; ++p)
       if (expect_false (p->revents)) /* this expect is debatable */
         {
-          --res;
..

thanks

-- 
lg



More information about the libev mailing list