1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-06 09:11:47 +02:00
nix/src/libutil/file-descriptor.cc
Sergei Zimmerman 96eeb6f4ff refactor(treewide): make some move ctors noexcept where appropriate
This is good practice to avoid pessimisations.
Left comments for the reasoning why ctors should be noexcept.
There are some tricky cases where we intentionally want throwing move ctors/assignments.
But those cases should really be reviewed, since some of those can be replaced
with more idiomatic copy/move-and-swap.
2024-11-09 12:09:33 +03:00

151 lines
2.8 KiB
C++

#include "file-system.hh"
#include "signals.hh"
#include "finally.hh"
#include "serialise.hh"
#include "util.hh"
#include <fcntl.h>
#include <unistd.h>
#ifdef _WIN32
# include <winnt.h>
# include <fileapi.h>
# include "windows-error.hh"
#endif
namespace nix {
void writeLine(Descriptor fd, std::string s)
{
s += '\n';
writeFull(fd, s);
}
std::string drainFD(Descriptor fd, bool block, const size_t reserveSize)
{
// the parser needs two extra bytes to append terminating characters, other users will
// not care very much about the extra memory.
StringSink sink(reserveSize + 2);
#ifdef _WIN32
// non-blocking is not supported this way on Windows
assert(block);
drainFD(fd, sink);
#else
drainFD(fd, sink, block);
#endif
return std::move(sink.s);
}
//////////////////////////////////////////////////////////////////////
AutoCloseFD::AutoCloseFD() : fd{INVALID_DESCRIPTOR} {}
AutoCloseFD::AutoCloseFD(Descriptor fd) : fd{fd} {}
// NOTE: This can be noexcept since we are just copying a value and resetting
// the file descriptor in the rhs.
AutoCloseFD::AutoCloseFD(AutoCloseFD && that) noexcept : fd{that.fd}
{
that.fd = INVALID_DESCRIPTOR;
}
AutoCloseFD & AutoCloseFD::operator =(AutoCloseFD && that)
{
close();
fd = that.fd;
that.fd = INVALID_DESCRIPTOR;
return *this;
}
AutoCloseFD::~AutoCloseFD()
{
try {
close();
} catch (...) {
ignoreExceptionInDestructor();
}
}
Descriptor AutoCloseFD::get() const
{
return fd;
}
void AutoCloseFD::close()
{
if (fd != INVALID_DESCRIPTOR) {
if(
#ifdef _WIN32
::CloseHandle(fd)
#else
::close(fd)
#endif
== -1)
/* This should never happen. */
throw NativeSysError("closing file descriptor %1%", fd);
fd = INVALID_DESCRIPTOR;
}
}
void AutoCloseFD::fsync() const
{
if (fd != INVALID_DESCRIPTOR) {
int result;
result =
#ifdef _WIN32
::FlushFileBuffers(fd)
#elif __APPLE__
::fcntl(fd, F_FULLFSYNC)
#else
::fsync(fd)
#endif
;
if (result == -1)
throw NativeSysError("fsync file descriptor %1%", fd);
}
}
void AutoCloseFD::startFsync() const
{
#if __linux__
if (fd != -1) {
/* Ignore failure, since fsync must be run later anyway. This is just a performance optimization. */
::sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE);
}
#endif
}
AutoCloseFD::operator bool() const
{
return fd != INVALID_DESCRIPTOR;
}
Descriptor AutoCloseFD::release()
{
Descriptor oldFD = fd;
fd = INVALID_DESCRIPTOR;
return oldFD;
}
//////////////////////////////////////////////////////////////////////
void Pipe::close()
{
readSide.close();
writeSide.close();
}
}