From: Jeff D. <jd...@ka...> - 2002-01-18 00:39:24
|
da...@co... said: > The attached patch is a somewhat ugly fix to my problem of having the > network interface hang. I'll describe the actual bug in case you want > to fix it in a more elegant way. > The bug boils down to the fact that poll(2) will overwrite the -> > revents field even when the ->events field was 0 going into the poll > call. See? Cool. Nice bug hunt and nice analysis. I hate the fix :-) Try the patch below and see if it fixes it as well. It survived a 2M packet ping flood with a find over the whole filesystem at the same time. Jeff --- um/arch/um/kernel/irq_user.c~ Sat Jan 12 20:53:42 2002 +++ um/arch/um/kernel/irq_user.c Thu Jan 17 19:31:04 2002 @@ -25,6 +25,7 @@ int irq; int pid; int events; + int current_events; }; static struct irq_fd *active_fds = NULL; @@ -53,18 +54,25 @@ break; } if(n == 0) break; + + irq_fd = active_fds; for(i = 0; i < pollfds_num; i++){ - if(pollfds[i].revents != 0) pollfds[i].events = 0; + if(pollfds[i].revents != 0){ + irq_fd->current_events = pollfds[i].events; + pollfds[i].events = 0; + } + irq_fd = irq_fd->next; } - i = 0; + for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ /* This mysterious assignment protects us against * the irq handler freeing the irq from under us. */ next = irq_fd->next; - if(pollfds[i].revents != 0) + if(irq_fd->current_events != 0){ + irq_fd->current_events = 0; do_IRQ(irq_fd->irq, usermode); - i++; + } } } } @@ -135,6 +143,7 @@ new_fd->fd = fd; new_fd->pid = pid; new_fd->events = events; + new_fd->current_events = 0; *last_irq_ptr = new_fd; last_irq_ptr = &new_fd->next; |