Skip to content

Commit

Permalink
posix_check WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jevinskie committed Mar 31, 2024
1 parent 488c76e commit 1ca9c99
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 9 deletions.
8 changes: 8 additions & 0 deletions include/redirect-to-os-log/redirect-to-os-log.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#pragma once

#include <source_location>
#include <unistd.h>

#define REDIRECT_LIKELY(cond) __builtin_expect((cond), 1)
#define REDIRECT_UNLIKELY(cond) __builtin_expect((cond), 0)

namespace redirect_to_os_log {

struct log_args {
Expand All @@ -19,4 +23,8 @@ extern ssize_t safe_write(int fd, const void *__nonnull buf, ssize_t count);
[[gnu::visibility("default")]]
extern void *__nullable io_loop(void *__nonnull arg);

[[gnu::visibility("default")]]
extern void posix_check(const int retval, const char *const __nonnull msg,
const std::source_location location = std::source_location::current());

} // namespace redirect_to_os_log
61 changes: 54 additions & 7 deletions lib/redirect-to-os-log/redirect-to-os-log-lib.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "redirect-to-os-log/redirect-to-os-log.hpp"

#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
Expand All @@ -18,8 +19,40 @@

extern "C" const char *const *const environ;

extern "C" [[gnu::noreturn, gnu::cold, gnu::format(__printf__, 1, 2)]]
void abort_report_np(const char *const __nonnull fmt, ...);

struct crashreporter_annotations_t {
uint64_t version;
char *message;
char *signature_string;
char *backtrace;
char *message2;
uint64_t thread;
uint32_t dialog_mode;
uint32_t padding0;
uint32_t abort_cause;
uint32_t padding1;
};

extern "C" {
[[gnu::visibility("hidden"), gnu::section("__DATA,__crash_info")]]
static crashreporter_annotations_t gCRAnnotations = {.version = 5};
}

extern "C" [[gnu::noreturn, gnu::cold, gnu::format(__printf__, 2, 3)]]
void _simple_dprintf(int fd, const char *const __nonnull fmt, ...);

namespace redirect_to_os_log {

static auto CRGetCrashLogMessage() {
return gCRAnnotations.message;
}

static void CRSetCrashLogMessage(char *msg) {
gCRAnnotations.message = msg;
}

static int stdout_pipe[2];
static int stderr_pipe[2];
int exit_pipe[2];
Expand All @@ -38,18 +71,30 @@ bool should_echo_from_env_var() {
return false;
}

void posix_check(const int retval, const char *const __nonnull msg,
const std::source_location location) {
const auto cerrno = errno;
if (REDIRECT_UNLIKELY(retval < 0)) {
abort_report_np("POSIX error: function: %s, file %s, line %u:%u: retval: %d errno: %d aka "
"'%s' description: '%s'.\n",
location.function_name(), location.file_name(), location.line(),
location.column(), retval, cerrno, strerror(cerrno), msg);
}
}

ssize_t safe_write(int fd, const void *__nonnull buf, ssize_t count) {
assert(count >= 0);
const auto written = count;
auto buffer = static_cast<const char *>(buf);

while (count > 0) {
ssize_t res = write(fd, buffer, static_cast<size_t>(count));
ssize_t res = write(fd, buffer, static_cast<size_t>(count));
const auto cerrno = errno;
if (res < 0) {
if (errno == EINTR) {
if (cerrno == EINTR) {
continue; // Interrupted by a signal, try again
} else {
assert(false && "safe_write failed");
posix_check(static_cast<int>(res), "safe_write");
}
}
buffer += res;
Expand All @@ -62,18 +107,20 @@ static void write_and_log(int fd, const std::string &line, bool echo) {
const size_t max_log_length = 1024;

if (echo) {
write(fd == STDOUT_FILENO ? STDOUT_FILENO : STDERR_FILENO, line.c_str(), line.length());
write(fd == STDOUT_FILENO ? STDOUT_FILENO : STDERR_FILENO, "\n", 1);
safe_write(fd == STDOUT_FILENO ? STDOUT_FILENO : STDERR_FILENO, line.c_str(),
static_cast<ssize_t>(line.length()));
safe_write(fd == STDOUT_FILENO ? STDOUT_FILENO : STDERR_FILENO, "\n", 1);
}

for (size_t pos = 0; pos < line.length(); pos += max_log_length) {
std::string chunk = line.substr(pos, max_log_length);
os_log_with_type(logger, fd == STDOUT_FILENO ? OS_LOG_TYPE_DEFAULT : OS_LOG_TYPE_ERROR,
os_log_with_type(fd == STDOUT_FILENO ? logger_stdout : logger_stderr,
fd == STDOUT_FILENO ? OS_LOG_TYPE_DEFAULT : OS_LOG_TYPE_ERROR,
"%{public}s", chunk.c_str());
}
}

static void log_output(int fd, os_log_t logger, bool echo) {
static void log_output(int fd, bool echo) {
char buffer[1024];
ssize_t bytes_read;

Expand Down
8 changes: 6 additions & 2 deletions tool/redirect-to-os-log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <cstring>
#include <filesystem>
#include <optional>
#include <spawn.h>
#include <sstream>
#include <sys/stat.h>
#include <system_error>
Expand Down Expand Up @@ -140,8 +141,11 @@ int main(int argc, const char *const *argv) {
}
}

const char *const *exe_argv = &argv[2 + do_echo];
const auto subsystem = exe_path.filename().c_str();
const auto exe_argv = &argv[2 + do_echo];
const auto subsystem = exe_path.filename().c_str();

posix_spawn_file_actions_t action;
posix_spawn_file_actions_init(&action);

// Run the I/O loop thread
redirect_to_os_log::log_args args = {
Expand Down

0 comments on commit 1ca9c99

Please sign in to comment.