Commit 72e396ca authored by Neel Goyal's avatar Neel Goyal Committed by Facebook Github Bot

Return 0 length iobuf if wrapping empty iovecs

Summary: Introduction of `folly::IOBuf::wrapIov` and the subsequent change to `WriteChainAsyncTransportWrapper` introduced a subtle change where someone sending a number of 0 length iovs would still get their WriteCallback invoked.   This fixes that case and also invokes WriteCallback if no iovs are to be wrapped.  Arguably, both of these are invalid uses of the API, but this at least fixes the subtleties.

Reviewed By: knekritz

Differential Revision: D9379661

fbshipit-source-id: 73d2f7cd1494be4ccccaa9c1fd834ae5410d6421
parent 942901df
......@@ -1021,7 +1021,7 @@ unique_ptr<IOBuf> IOBuf::wrapIov(const iovec* vec, size_t count) {
size_t len = vec[i].iov_len;
void* data = vec[i].iov_base;
if (len > 0) {
auto buf = folly::IOBuf::wrapBuffer(data, len);
auto buf = wrapBuffer(data, len);
if (!result) {
result = std::move(buf);
} else {
......@@ -1029,6 +1029,9 @@ unique_ptr<IOBuf> IOBuf::wrapIov(const iovec* vec, size_t count) {
}
}
}
if (UNLIKELY(result == nullptr)) {
return create(0);
}
return result;
}
......
......@@ -1224,8 +1224,8 @@ class IOBuf {
size_t fillIov(struct iovec* iov, size_t len) const;
/**
* A helper that wraps a number of iovecs into an IOBuf chain. Empty iovecs
* are ignored. If no data is wrapped, nullptr is returned.
* A helper that wraps a number of iovecs into an IOBuf chain. If count == 0,
* then a zero length buf is returned. This function never returns nullptr.
*/
static std::unique_ptr<IOBuf> wrapIov(const iovec* vec, size_t count);
......
......@@ -45,9 +45,7 @@ class WriteChainAsyncTransportWrapper
size_t count,
folly::WriteFlags flags = folly::WriteFlags::NONE) override {
auto writeBuffer = folly::IOBuf::wrapIov(vec, count);
if (writeBuffer) {
writeChain(callback, std::move(writeBuffer), flags);
}
writeChain(callback, std::move(writeBuffer), flags);
}
/**
......
......@@ -1024,7 +1024,14 @@ TEST(IOBuf, wrapZeroLenIov) {
iov.push_back({nullptr, 0});
iov.push_back({nullptr, 0});
auto wrapped = IOBuf::wrapIov(iov.data(), iov.size());
EXPECT_EQ(nullptr, wrapped);
EXPECT_NE(nullptr, wrapped);
EXPECT_EQ(wrapped->countChainElements(), 1);
EXPECT_EQ(wrapped->length(), 0);
wrapped = IOBuf::wrapIov(nullptr, 0);
EXPECT_NE(nullptr, wrapped);
EXPECT_EQ(wrapped->countChainElements(), 1);
EXPECT_EQ(wrapped->length(), 0);
}
TEST(IOBuf, move) {
......
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