devpoll write feigns success in the face of EINTR
A community member reported troubling behavior from their haskell application which leveraged epoll for socket events. A varying amount of time after startup, while under typical (not stifling) load, the app would cease accepting connections on its listening socket. Further investigation indicated that none of the epoll handles in the process held a registration for the listening socket.
It initially appeared as if the application was failing to reregister for events on the socket after exhausting the event queue. After much dtracing, an interesting data point was found:
(OUTPUT FILTERED FOR CLARITY) 342746211772758 4 accept 18 30 342746211778025 4 accept 18 -1 342746212050717 4 entry epoll-ctl 23 1 342746212054211 4 getf ffffff026c1018d8 342746212058522 12 eventfd-write 17 0 342746212063283 4 poll-add ffffff025ed9c5d8 23 1004 342746212070369 3 poll-event ffffff026a74fc20 28 00000001 FADF7A190000001C 342746212074958 11 eventfd-write 17 0 342746212082453 11 entry epoll-ctl 18 3 342746212094178 4 dpwrite 3 0 342746212095032 3 epoll-wait 11 1 342746212096178 11 dpwrite 3 4 342746212097933 4 return epoll-ctl-return 23 0 342746212107415 11 return epoll-ctl-return 18 0
Here we see the tid-11 dpwrite fail with EINTR due to its race with tid-4. Despite that, epoll_ctl returns 0, falsely reporting success. Taking a look at the write(2) source gives us a hit as to why:
cnt -= auio.uio_resid; ... if (error == EINTR && cnt != 0) error = 0;
If any data appears to be successfully written (as indicated by movement from uio_resid), then write(2) suppresses the EINTR. It was no surprise to find dpwrite performing a uiomove() prior to the point where it would emit EINTR.
Updated by Electric Monk about 3 years ago
- Status changed from New to Closed
commit 57a0264b71e479ed0dc19299607d662043907cb6 Author: Patrick Mooney <email@example.com> Date: 2016-10-11T15:01:08.000Z 7422 dpioctl should pay attention to FKIOCTL 7423 epoll_ctl should throw EINVAL for loops 7424 epoll should not leave dangling polldat_t entries 7425 devpoll write feigns success in the face of EINTR 7426 epoll_ctl not allowed to emit EINTR Reviewed by: Jerry Jelinek <firstname.lastname@example.org> Reviewed by: Bryan Cantrill <email@example.com> Approved by: Dan McDonald <firstname.lastname@example.org>