Project

General

Profile

Bug #7425

devpoll write feigns success in the face of EINTR

Added by Robert Mustacchi about 3 years ago. Updated about 3 years ago.

Status:
Closed
Priority:
Normal
Category:
kernel
Start date:
2016-09-27
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:

Description

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.

History

#1

Updated by Electric Monk about 3 years ago

  • Status changed from New to Closed

git commit 57a0264b71e479ed0dc19299607d662043907cb6

commit  57a0264b71e479ed0dc19299607d662043907cb6
Author: Patrick Mooney <pmooney@pfmooney.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 <jerry.jelinek@joyent.com>
    Reviewed by: Bryan Cantrill <bryan@joyent.com>
    Approved by: Dan McDonald <danmcd@omniti.com>

Also available in: Atom PDF