Merge changes Iba04f70f,I6b5bd980 into main

* changes:
  rl-next: fix mistake in issue number
  crash handling: log to syslog also
This commit is contained in:
jade
2025-02-23 07:56:32 +00:00
committed by Gerrit Code Review
8 changed files with 63 additions and 34 deletions
+12
View File
@@ -0,0 +1,12 @@
---
synopsis: "Crashs land in syslog now"
cls: [2640]
category: Improvements
credits: [jade]
---
When Lix crashes with unexpected exceptions and in some other conditions, it prints bug reporting instructions.
Previously, these only landed in stderr and not in syslog.
However, on larger Lix installations, it may be the case that Lix crashes in the client without the logs landing in the system logs, which impeded diagnosis.
Now, such crashes always land in syslog too.
+1 -1
View File
@@ -1,6 +1,6 @@
---
synopsis: "Paralellise `nix store sign` using a thread pool"
issues: [399]
issues: [fj#399]
cls: [2606]
category: Fixes
credits: [Lunaphied]
+8 -6
View File
@@ -1,5 +1,6 @@
#include "lix/libmain/crash-handler.hh"
#include "lix/libutil/fmt.hh"
#include "lix/libutil/logging.hh"
#include <boost/core/demangle.hpp>
#include <exception>
@@ -7,24 +8,25 @@
namespace nix {
namespace {
void onTerminate()
{
std::cerr << "Lix crashed. This is a bug. We would appreciate if you report it along with what caused it at https://git.lix.systems/lix-project/lix/issues with the following information included:\n\n";
logFatal("Lix crashed. This is a bug. We would appreciate if you report it along with what caused it at https://git.lix.systems/lix-project/lix/issues with the following information included:\n");
try {
std::exception_ptr eptr = std::current_exception();
if (eptr) {
std::rethrow_exception(eptr);
} else {
std::cerr << "std::terminate() called without exception\n";
logFatal("std::terminate() called without exception");
}
} catch (const std::exception & ex) {
std::cerr << "Exception: " << boost::core::demangle(typeid(ex).name()) << ": " << ex.what() << "\n";
logFatal(fmt("Exception: %s: %s", boost::core::demangle(typeid(ex).name()), ex.what()));
} catch (...) {
std::cerr << "Unknown exception! Spooky.\n";
logFatal("Unknown exception! Spooky.");
}
std::cerr << "Stack trace:\n";
nix::printStackTrace();
logFatal("Stack trace:");
logFatal(getStackTrace());
std::abort();
}
+2 -2
View File
@@ -18,8 +18,8 @@ struct ErrorHandler : kj::TaskSet::ErrorHandler
{
void taskFailed(kj::Exception && e) override
{
printError("unexpected async failure in Worker: %s", kj::str(e).cStr());
abort();
logFatal(fmt("unexpected async failure in Worker: %s", kj::str(e).cStr()));
std::terminate();
}
} errorHandler;
}
+5 -2
View File
@@ -1,4 +1,5 @@
#include "lix/libutil/fmt.hh" // IWYU pragma: keep
#include <sstream>
// Darwin and FreeBSD stdenv do not define _GNU_SOURCE but do have _Unwind_Backtrace.
#if __APPLE__ || __FreeBSD__
#define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED
@@ -16,9 +17,11 @@ template HintFmt::HintFmt(const std::string &, const uint64_t &, const char * co
HintFmt::HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {}
void printStackTrace()
std::string getStackTrace()
{
std::cerr << boost::stacktrace::stacktrace() << std::endl;
std::stringstream ss;
ss << boost::stacktrace::stacktrace();
return ss.str();
}
}
+2 -2
View File
@@ -11,8 +11,8 @@ extern template class boost::basic_format<char>;
namespace nix {
/** Prints a C++ stack trace to stderr using boost stacktrace */
void printStackTrace();
/** Gets a C++ stack trace using boost stacktrace */
std::string getStackTrace();
/**
* Values wrapped in this struct are printed in magenta.
+29 -21
View File
@@ -10,6 +10,7 @@
#include <mutex>
#include <sstream>
#include <nlohmann/json.hpp>
#include <syslog.h>
namespace nix {
@@ -126,27 +127,6 @@ Verbosity verbosityFromIntClamped(int val)
return static_cast<Verbosity>(clamped);
}
void writeLogsToStderr(std::string_view s)
{
static std::mutex lock;
// make sure only one thread uses this function at any given time.
// multiple concurrent threads can have deleterious effects on log
// output, especially when layering structured formats (like JSON)
// on top of a SimpleLogger which is itself not thread-safe. every
// Logger instance should be thread-safe in an ideal world, but we
// cannot really enforce that on a per-logger level at this point.
std::unique_lock _lock(lock);
try {
writeFull(STDERR_FILENO, s, false);
} catch (SysError & 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
unexpectedly. */
}
}
Logger * makeSimpleLogger(bool printBuildLogs)
{
return new SimpleLogger(printBuildLogs);
@@ -367,4 +347,32 @@ Activity::~Activity()
}
}
void writeLogsToStderr(std::string_view s)
{
static std::mutex lock;
// make sure only one thread uses this function at any given time.
// multiple concurrent threads can have deleterious effects on log
// output, especially when layering structured formats (like JSON)
// on top of a SimpleLogger which is itself not thread-safe. every
// Logger instance should be thread-safe in an ideal world, but we
// cannot really enforce that on a per-logger level at this point.
std::unique_lock _lock(lock);
try {
writeFull(STDERR_FILENO, s, false);
} catch (SysError & 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
unexpectedly. */
}
}
void logFatal(std::string const & s)
{
writeLogsToStderr(s + "\n");
// std::string for guaranteed null termination
syslog(LOG_CRIT, "%s", s.c_str());
}
}
+4
View File
@@ -280,4 +280,8 @@ inline void warn(const std::string & fs, const Args & ... args)
void writeLogsToStderr(std::string_view s);
/** Logs a fatal message as loudly as possible. This will go into syslog as well as stderr.
* The purpose of this function is making failures with redirected stderr louder. */
void logFatal(std::string const & s);
}