Commit c6bdae86 authored by Philip Pronin's avatar Philip Pronin Committed by Tudor Bosman

fix AsyncIO::doWait

Summary:
As it turns out, `io_getevents` may actually return less than
`min_nr` events.  According to the aio logic
(https://github.com/torvalds/linux/blob/10b5b5361a3c2a7fff9dbfa0f127adc2531e7732/fs/aio.c#L1634),
there may be a couple of rounds required to get at least `nr_min` events, and
if interrupted after the first one, incomplete results would be returned

Test Plan:
fbconfig -r folly/experimental/io/test && fbmake runtests_opt -32

and was no longer able to repro #4609062

Reviewed By: soren@fb.com

FB internal diff: D1410389

Tasks: 4609062
parent 09a81a96
......@@ -19,9 +19,9 @@
#include <sys/eventfd.h>
#include <unistd.h>
#include <cerrno>
#include <ostream>
#include <stdexcept>
#include <string>
#include <fstream>
#include <boost/intrusive/parent_from_member.hpp>
#include <glog/logging.h>
......@@ -220,13 +220,25 @@ Range<AsyncIO::Op**> AsyncIO::pollCompleted() {
Range<AsyncIO::Op**> AsyncIO::doWait(size_t minRequests, size_t maxRequests) {
io_event events[maxRequests];
int count;
size_t count = 0;
do {
int ret;
do {
// Wait forever
count = io_getevents(ctx_, minRequests, maxRequests, events, nullptr);
} while (count == -EINTR);
checkKernelError(count, "AsyncIO: io_getevents failed");
DCHECK_GE(count, minRequests); // the man page says so
// GOTCHA: io_getevents() may returns less than min_nr results if
// interrupted after some events have been read (if before, -EINTR
// is returned).
ret = io_getevents(ctx_,
minRequests - count,
maxRequests - count,
events + count,
/* timeout */ nullptr); // wait forever
} while (ret == -EINTR);
// Check as may not be able to recover without leaking events.
CHECK_GE(ret, 0)
<< "AsyncIO: io_getevents failed with error " << errnoStr(-ret);
count += ret;
} while (count < minRequests);
DCHECK_LE(count, maxRequests);
completed_.clear();
......
......@@ -25,8 +25,8 @@
#include <cstdint>
#include <deque>
#include <functional>
#include <iosfwd>
#include <mutex>
#include <ostream>
#include <utility>
#include <vector>
......@@ -233,6 +233,7 @@ class AsyncIOQueue {
*/
typedef std::function<AsyncIOOp*()> OpFactory;
void submit(OpFactory op);
private:
void onCompleted(AsyncIOOp* op);
void maybeDequeue();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment