[block-cache] fix potential file descriptor leak
Encapsulate file descriptor into an object, to ensure that an fd will be closed properly while exception raised, e.g., the block_cache throws exception during the block_manager's construction.
This commit is contained in:
@ -39,14 +39,16 @@ namespace {
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
int
|
||||
file_utils::open_file(string const &path, int flags) {
|
||||
int fd = ::open(path.c_str(), OPEN_FLAGS | flags, DEFAULT_MODE);
|
||||
if (fd < 0)
|
||||
file_utils::file_descriptor::file_descriptor(string const &path, int flags) {
|
||||
fd_ = ::open(path.c_str(), OPEN_FLAGS | flags, DEFAULT_MODE);
|
||||
if (fd_ < 0)
|
||||
syscall_failed("open",
|
||||
"Note: you cannot run this tool with these options on live metadata.");
|
||||
}
|
||||
|
||||
return fd;
|
||||
file_utils::file_descriptor::~file_descriptor() {
|
||||
close(fd_);
|
||||
fd_ = -1;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -76,7 +78,7 @@ file_utils::check_file_exists(string const &file, bool must_be_regular_file) {
|
||||
throw runtime_error("Not a regular file");
|
||||
}
|
||||
|
||||
int
|
||||
file_utils::file_descriptor
|
||||
file_utils::create_block_file(string const &path, off_t file_size) {
|
||||
if (file_exists(path)) {
|
||||
ostringstream out;
|
||||
@ -84,16 +86,16 @@ file_utils::create_block_file(string const &path, off_t file_size) {
|
||||
throw runtime_error(out.str());
|
||||
}
|
||||
|
||||
int fd = open_file(path, O_CREAT | O_EXCL | O_RDWR);
|
||||
file_descriptor fd(path, O_CREAT | O_EXCL | O_RDWR);
|
||||
|
||||
int r = ::ftruncate(fd, file_size);
|
||||
int r = ::ftruncate(fd.fd_, file_size);
|
||||
if (r < 0)
|
||||
syscall_failed("ftruncate");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
file_utils::file_descriptor
|
||||
file_utils::open_block_file(string const &path, off_t min_size, bool writeable, bool excl) {
|
||||
if (!file_exists(path)) {
|
||||
ostringstream out;
|
||||
@ -105,7 +107,7 @@ file_utils::open_block_file(string const &path, off_t min_size, bool writeable,
|
||||
if (excl)
|
||||
flags |= O_EXCL;
|
||||
|
||||
return open_file(path, flags);
|
||||
return file_descriptor(path, flags);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@ -146,17 +148,15 @@ file_utils::zero_superblock(std::string const &path)
|
||||
{
|
||||
char *buffer;
|
||||
unsigned const SUPERBLOCK_SIZE = 4096;
|
||||
int fd = open_block_file(path, SUPERBLOCK_SIZE, true, true);
|
||||
file_descriptor fd = open_block_file(path, SUPERBLOCK_SIZE, true, true);
|
||||
|
||||
buffer = reinterpret_cast<char *>(aligned_alloc(SUPERBLOCK_SIZE, SUPERBLOCK_SIZE));
|
||||
if (!buffer)
|
||||
throw runtime_error("out of memory");
|
||||
|
||||
memset(buffer, 0, SUPERBLOCK_SIZE);
|
||||
if (::write(fd, buffer, SUPERBLOCK_SIZE) != SUPERBLOCK_SIZE)
|
||||
if (::write(fd.fd_, buffer, SUPERBLOCK_SIZE) != SUPERBLOCK_SIZE)
|
||||
throw runtime_error("couldn't zero superblock");
|
||||
|
||||
::close(fd);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user