Commit c7796707 authored by Tudor Bosman's avatar Tudor Bosman Committed by Jordan DeLong

fix ~File crash in debug mode

Test Plan: test added

Reviewed By: tjackson@fb.com

FB internal diff: D630163
parent e4d6eb2a
......@@ -37,7 +37,6 @@ void File::close() {
}
bool File::closeNoThrow() {
DCHECK(fd_ != -1);
int r = ownsFd_ ? ::close(fd_) : 0;
release();
return r == 0;
......
......@@ -37,8 +37,10 @@ class FileReader : public GenImpl<ByteRange, FileReader> {
template <class Body>
bool apply(Body&& body) const {
for (;;) {
ssize_t n = ::read(file_.fd(), buffer_->writableTail(),
buffer_->capacity());
ssize_t n;
do {
n = ::read(file_.fd(), buffer_->writableTail(), buffer_->capacity());
} while (n == -1 && errno == EINTR);
if (n == -1) {
throw std::system_error(errno, std::system_category(), "read failed");
}
......@@ -91,11 +93,10 @@ class FileWriter : public Operator<FileWriter> {
void write(ByteRange v) const {
ssize_t n;
while (!v.empty()) {
do {
n = ::write(file_.fd(), v.data(), v.size());
} while (n == -1 && errno == EINTR);
if (n == -1) {
if (errno == EINTR) {
continue;
}
throw std::system_error(errno, std::system_category(),
"write() failed");
}
......
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "folly/experimental/File.h"
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "folly/Benchmark.h"
#include "folly/String.h"
using namespace folly;
namespace {
void expectWouldBlock(ssize_t r) {
int savedErrno = errno;
EXPECT_EQ(-1, r);
EXPECT_EQ(EAGAIN, savedErrno) << errnoStr(errno);
}
void expectOK(ssize_t r) {
int savedErrno = errno;
EXPECT_LE(0, r) << ": errno=" << errnoStr(errno);
}
} // namespace
TEST(File, Simple) {
// Open a file, ensure it's indeed open for reading
char buf = 'x';
{
File f("/etc/hosts");
EXPECT_NE(-1, f.fd());
EXPECT_EQ(1, ::read(f.fd(), &buf, 1));
f.close();
EXPECT_EQ(-1, f.fd());
}
}
TEST(File, OwnsFd) {
// Wrap a file descriptor, make sure that ownsFd works
// We'll test that the file descriptor is closed by closing the writing
// end of a pipe and making sure that a non-blocking read from the reading
// end returns 0.
char buf = 'x';
int p[2];
expectOK(::pipe(p));
int flags = ::fcntl(p[0], F_GETFL);
expectOK(flags);
expectOK(::fcntl(p[0], F_SETFL, flags | O_NONBLOCK));
expectWouldBlock(::read(p[0], &buf, 1));
{
File f(p[1]);
EXPECT_EQ(p[1], f.fd());
}
// Ensure that moving the file doesn't close it
{
File f(p[1]);
EXPECT_EQ(p[1], f.fd());
File f1(std::move(f));
EXPECT_EQ(-1, f.fd());
EXPECT_EQ(p[1], f1.fd());
}
expectWouldBlock(::read(p[0], &buf, 1)); // not closed
{
File f(p[1], true);
EXPECT_EQ(p[1], f.fd());
}
ssize_t r = ::read(p[0], &buf, 1); // eof
expectOK(r);
EXPECT_EQ(0, r);
::close(p[0]);
}
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