void AsyncPipeReader::handlerReady(uint16_t events) noexcept { DestructorGuard dg(this); CHECK(events & EventHandler::READ); VLOG(5) << "AsyncPipeReader::handlerReady() this=" << this << ", fd=" << fd_; assert(readCallback_ != nullptr); while (readCallback_) { // - What API does callback support? const auto movable = readCallback_->isBufferMovable(); // noexcept // Get the buffer to read into. void* buf = nullptr; size_t buflen = 0; std::unique_ptr<IOBuf> ioBuf; if (movable) { ioBuf = IOBuf::create(readCallback_->maxBufferSize()); buf = ioBuf->writableBuffer(); buflen = ioBuf->capacity(); } else { try { readCallback_->getReadBuffer(&buf, &buflen); } catch (const std::exception& ex) { AsyncSocketException aex( AsyncSocketException::BAD_ARGS, string("ReadCallback::getReadBuffer() " "threw exception: ") + ex.what()); failRead(aex); return; } catch (...) { AsyncSocketException aex( AsyncSocketException::BAD_ARGS, string("ReadCallback::getReadBuffer() " "threw non-exception type")); failRead(aex); return; } if (buf == nullptr || buflen == 0) { AsyncSocketException aex( AsyncSocketException::INVALID_STATE, string("ReadCallback::getReadBuffer() " "returned empty buffer")); failRead(aex); return; } } // Perform the read #if _WIN32 // On Windows you can't call read on a socket, so call recv instead. ssize_t bytesRead = folly::fileutil_detail::wrapNoInt(recv_internal, fd_, buf, buflen); #else ssize_t bytesRead = folly::readNoInt(fd_.toFd(), buf, buflen); #endif if (bytesRead > 0) { if (movable) { ioBuf->append(std::size_t(bytesRead)); readCallback_->readBufferAvailable(std::move(ioBuf)); } else { readCallback_->readDataAvailable(size_t(bytesRead)); } // Fall through and continue around the loop if the read // completely filled the available buffer. // Note that readCallback_ may have been uninstalled or changed inside // readDataAvailable(). if (static_cast<size_t>(bytesRead) < buflen) { return; } } else if (bytesRead < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { // No more data to read right now. return; } else if (bytesRead < 0) { AsyncSocketException ex( AsyncSocketException::INVALID_STATE, "read failed", errno); failRead(ex); return; } else { assert(bytesRead == 0); // EOF unregisterHandler(); AsyncReader::ReadCallback* callback = readCallback_; readCallback_ = nullptr; callback->readEOF(); return; } // Max reads per loop? } }
void AsyncPipeReader::handlerReady(uint16_t events) noexcept { DestructorGuard dg(this); CHECK(events & EventHandler::READ); VLOG(5) << "AsyncPipeReader::handlerReady() this=" << this << ", fd=" << fd_; assert(readCallback_ != nullptr); while (readCallback_) { // Get the buffer to read into. void* buf = nullptr; size_t buflen = 0; try { readCallback_->getReadBuffer(&buf, &buflen); } catch (const std::exception& ex) { AsyncSocketException aex(AsyncSocketException::BAD_ARGS, string("ReadCallback::getReadBuffer() " "threw exception: ") + ex.what()); failRead(aex); return; } catch (...) { AsyncSocketException ex(AsyncSocketException::BAD_ARGS, string("ReadCallback::getReadBuffer() " "threw non-exception type")); failRead(ex); return; } if (buf == nullptr || buflen == 0) { AsyncSocketException ex(AsyncSocketException::INVALID_STATE, string("ReadCallback::getReadBuffer() " "returned empty buffer")); failRead(ex); return; } // Perform the read ssize_t bytesRead = folly::readNoInt(fd_, buf, buflen); if (bytesRead > 0) { readCallback_->readDataAvailable(bytesRead); // Fall through and continue around the loop if the read // completely filled the available buffer. // Note that readCallback_ may have been uninstalled or changed inside // readDataAvailable(). if (static_cast<size_t>(bytesRead) < buflen) { return; } } else if (bytesRead < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { // No more data to read right now. return; } else if (bytesRead < 0) { AsyncSocketException ex(AsyncSocketException::INVALID_STATE, "read failed", errno); failRead(ex); return; } else { assert(bytesRead == 0); // EOF unregisterHandler(); AsyncReader::ReadCallback* callback = readCallback_; readCallback_ = nullptr; callback->readEOF(); return; } // Max reads per loop? } }