mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2025-12-31 07:49:35 -06:00
...most notably we now produce fully static binaries in an alpine
image.
A few assorted thoughts:
* I really like static binaries, ideally I'd like to run EggsFS
deployments with just systemd scripts and a few binaries.
* Go already does this, which is great.
* C++ does not, which is less great.
* Linking statically against `glibc` works, but is unsupported.
Not only stuff like NSS (which `gethostbyname` requires)
straight up does not work, unless you build `glibc` with
unsupported and currently apparently broken flags
(`--enable-static-nss`), but also other stuff is subtly
broken (I couldn't remember exactly what was broken,
but see comments such as
<https://github.com/haskell/haskell-language-server/issues/2431#issuecomment-985880838>).
* So we're left with alternative libcs -- the most popular being
musl.
* The simplest way to build a C++ application using musl is to just
build on a system where musl is already the default libc -- such
as alpine linux.
The backtrace support is in a bit of a bad state. Exception stacktraces
work on musl, but DWARF seems to be broken on the normal release build.
Moreover, libunwind doesn't play well with musl's signal handler:
<https://maskray.me/blog/2022-04-10-unwinding-through-signal-handler>.
Keeping it working seems to be a bit of a chore, and I'm going to revisit
it later.
In the meantime, gdb stack traces do work fine.
50 lines
1.6 KiB
C++
50 lines
1.6 KiB
C++
// #include <bits/types/struct_timespec.h>
|
|
#include <cstdio>
|
|
#include <time.h>
|
|
|
|
#include "Exception.hpp"
|
|
#include "Time.hpp"
|
|
#include "Assert.hpp"
|
|
|
|
std::ostream& operator<<(std::ostream& out, Duration d) {
|
|
if (d.ns < 1'000) {
|
|
out << d.ns << "ns";
|
|
} else if (d.ns < 1'000'000) {
|
|
out << d.ns/1'000 << "." << d.ns%1'000 << "us";
|
|
} else if (d.ns < 1'000'000'000) {
|
|
out << d.ns/1'000'000 << "." << d.ns%1'000'000 << "ms";
|
|
} else if (d.ns < 1'000'000'000ull*60) {
|
|
out << d.ns/1'000'000'000 << "." << d.ns%1'000'000'000 << "s";
|
|
} else if (d.ns < 1'000'000'000ull*60*60) {
|
|
out << d.ns/(1'000'000'000ull*60) << "." << d.ns%(1'000'000'000ull*60) << "m";
|
|
} else {
|
|
out << d.ns/(1'000'000'000ull*60*60) << "." << d.ns%(1'000'000'000ull*60*60) << "h";
|
|
}
|
|
return out;
|
|
}
|
|
|
|
EggsTime eggsNow() {
|
|
struct timespec now;
|
|
|
|
if (clock_gettime(CLOCK_REALTIME, &now) != 0) {
|
|
throw SYSCALL_EXCEPTION("clock_gettime");
|
|
}
|
|
|
|
return EggsTime(((uint64_t)now.tv_nsec + ((uint64_t)now.tv_sec * 1'000'000'000ull)) - EGGS_EPOCH);
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& out, EggsTime eggst) {
|
|
time_t secs = (EGGS_EPOCH + eggst.ns) / 1'000'000'000ull;
|
|
uint64_t nsecs = eggst.ns % 1'000'000'00ull;
|
|
struct tm tm;
|
|
if (gmtime_r(&secs, &tm) == nullptr) {
|
|
throw SYSCALL_EXCEPTION("gmtime_r");
|
|
}
|
|
// "2006-01-02T15:04:05.999999999"
|
|
char buf[31];
|
|
ALWAYS_ASSERT(strftime(buf, 29, "%Y-%m-%dT%H:%M:%S.", &tm) == 20);
|
|
ALWAYS_ASSERT(snprintf(buf+20, 10, "%09lu", nsecs) == 9);
|
|
buf[30] = '\0';
|
|
out << buf;
|
|
return out;
|
|
} |