mirror of
https://github.com/NixOS/nix
synced 2025-07-06 13:21:47 +02:00
Separate SystemError
from SysError
Most of this is a `catch SysError` -> `catch SystemError` sed. This is a rather pure-churn change I would like to get out of the way. **The intersting part is `src/libutil/error.hh`.** On Unix, we will only throw the `SysError` concrete class, which has the same constructors that `SystemError` used to have. On Windows, we will throw `WinError` *and* `SysError`. `WinError` (which will be created in a later PR), will use a `DWORD` instead of `int` error value, and `GetLastError()`, which is the Windows equivalent of the `errno` machinery. Windows will *also* use `SysError` because Window's "libc" (MSVCRT) implements the POSIX interface, and we use it too. As the docs describe, while we *throw* one of the 3 choices above (2 concrete classes or the alias), we should always *catch* `SystemError`. This ensures no matter how the implementation changes for Windows (e.g. between `SysError` and `WinError`) the catching logic stays the same and stays correct. Co-Authored-By volth <volth@volth.com> Co-Authored-By Eugene Butler <eugene@eugene4.com>
This commit is contained in:
parent
0d55d660d5
commit
6208ca7209
19 changed files with 59 additions and 27 deletions
|
@ -304,7 +304,7 @@ void RootArgs::parseCmdline(const Strings & _cmdline, bool allowShebang)
|
|||
for (auto pos = savedArgs.begin(); pos != savedArgs.end();pos++)
|
||||
cmdline.push_back(*pos);
|
||||
}
|
||||
} catch (SysError &) { }
|
||||
} catch (SystemError &) { }
|
||||
}
|
||||
for (auto pos = cmdline.begin(); pos != cmdline.end(); ) {
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ static CgroupStats destroyCgroup(const Path & cgroup, bool returnStats)
|
|||
using namespace std::string_literals;
|
||||
warn("killing stray builder process %d (%s)...",
|
||||
pid, trim(replaceStrings(cmdline, "\0"s, " ")));
|
||||
} catch (SysError &) {
|
||||
} catch (SystemError &) {
|
||||
}
|
||||
}
|
||||
// FIXME: pid wraparound
|
||||
|
|
|
@ -124,7 +124,7 @@ static void applyConfigInner(const std::string & contents, const std::string & p
|
|||
try {
|
||||
std::string includedContents = readFile(path);
|
||||
applyConfigInner(includedContents, p, parsedContents);
|
||||
} catch (SysError &) {
|
||||
} catch (SystemError &) {
|
||||
// TODO: Do we actually want to ignore this? Or is it better to fail?
|
||||
}
|
||||
} else if (!ignoreMissing) {
|
||||
|
|
|
@ -178,20 +178,50 @@ MakeError(Error, BaseError);
|
|||
MakeError(UsageError, Error);
|
||||
MakeError(UnimplementedError, Error);
|
||||
|
||||
class SysError : public Error
|
||||
/**
|
||||
* To use in catch-blocks.
|
||||
*/
|
||||
MakeError(SystemError, Error);
|
||||
|
||||
/**
|
||||
* POSIX system error, created using `errno`, `strerror` friends.
|
||||
*
|
||||
* Throw this, but prefer not to catch this, and catch `SystemError`
|
||||
* instead. This allows implementations to freely switch between this
|
||||
* and `WinError` without breaking catch blocks.
|
||||
*
|
||||
* However, it is permissible to catch this and rethrow so long as
|
||||
* certain conditions are not met (e.g. to catch only if `errNo =
|
||||
* EFooBar`). In that case, try to also catch the equivalent `WinError`
|
||||
* code.
|
||||
*
|
||||
* @todo Rename this to `PosixError` or similar. At this point Windows
|
||||
* support is too WIP to justify the code churn, but if it is finished
|
||||
* then a better identifier becomes moe worth it.
|
||||
*/
|
||||
class SysError : public SystemError
|
||||
{
|
||||
public:
|
||||
int errNo;
|
||||
|
||||
/**
|
||||
* Construct using the explicitly-provided error number. `strerror`
|
||||
* will be used to try to add additional information to the message.
|
||||
*/
|
||||
template<typename... Args>
|
||||
SysError(int errNo_, const Args & ... args)
|
||||
: Error("")
|
||||
SysError(int errNo, const Args & ... args)
|
||||
: SystemError(""), errNo(errNo)
|
||||
{
|
||||
errNo = errNo_;
|
||||
auto hf = hintfmt(args...);
|
||||
err.msg = hintfmt("%1%: %2%", normaltxt(hf.str()), strerror(errNo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct using the ambient `errno`.
|
||||
*
|
||||
* Be sure to not perform another `errno`-modifying operation before
|
||||
* calling this constructor!
|
||||
*/
|
||||
template<typename... Args>
|
||||
SysError(const Args & ... args)
|
||||
: SysError(errno, args ...)
|
||||
|
@ -199,7 +229,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/** Throw an exception for the purpose of checking that exception handling works; see 'initLibUtil()'.
|
||||
/**
|
||||
* Throw an exception for the purpose of checking that exception
|
||||
* handling works; see 'initLibUtil()'.
|
||||
*/
|
||||
void throwExceptionSelfCheck();
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ void closeMostFDs(const std::set<int> & exceptions)
|
|||
}
|
||||
}
|
||||
return;
|
||||
} catch (SysError &) {
|
||||
} catch (SystemError &) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ void writeToStderr(std::string_view s)
|
|||
{
|
||||
try {
|
||||
writeFull(STDERR_FILENO, s, false);
|
||||
} catch (SysError & e) {
|
||||
} catch (SystemError & e) {
|
||||
/* Ignore failing writes to stderr. We need to ignore write
|
||||
errors to ensure that cleanup code that logs to stderr runs
|
||||
to completion if the other side of stderr has been closed
|
||||
|
|
|
@ -53,7 +53,7 @@ void FdSink::writeUnbuffered(std::string_view data)
|
|||
written += data.size();
|
||||
try {
|
||||
writeFull(fd, data);
|
||||
} catch (SysError & e) {
|
||||
} catch (SystemError & e) {
|
||||
_good = false;
|
||||
throw;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ void initLibUtil() {
|
|||
// When exception handling fails, the message tends to be printed by the
|
||||
// C++ runtime, followed by an abort.
|
||||
// For example on macOS we might see an error such as
|
||||
// libc++abi: terminating with uncaught exception of type nix::SysError: error: C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded.
|
||||
// libc++abi: terminating with uncaught exception of type nix::SystemError: error: C++ exception handling is broken. This would appear to be a problem with the way Nix was compiled and/or linked and/or loaded.
|
||||
bool caught = false;
|
||||
try {
|
||||
throwExceptionSelfCheck();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue