mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-13 22:49:11 +00:00
Work towards improving signals and processes
This commit is contained in:
parent
de703b182c
commit
d7ac16a9ed
96 changed files with 1474 additions and 427 deletions
|
@ -22,6 +22,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
|
@ -40,7 +41,7 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
|
|||
ssize_t got;
|
||||
intptr_t addr;
|
||||
size_t i, j, gi;
|
||||
int rc, pid, pipefds[2];
|
||||
int ws, pid, pipefds[2];
|
||||
struct Garbages *garbage;
|
||||
const struct StackFrame *frame;
|
||||
const char *debugbin, *p1, *p2, *p3, *addr2line;
|
||||
|
@ -73,7 +74,7 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
|
|||
close(pipefds[0]);
|
||||
close(pipefds[1]);
|
||||
execvp(addr2line, argv);
|
||||
abort();
|
||||
_exit(127);
|
||||
}
|
||||
close(pipefds[1]);
|
||||
while ((got = read(pipefds[0], buf, kBacktraceBufSize)) > 0) {
|
||||
|
@ -99,9 +100,15 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
|
|||
}
|
||||
}
|
||||
close(pipefds[0]);
|
||||
if (waitpid(pid, &rc, 0) == -1) return -1;
|
||||
if (WEXITSTATUS(rc) != 0) return -1;
|
||||
return 0;
|
||||
while (waitpid(pid, &ws, 0) == -1) {
|
||||
if (errno == EINTR) continue;
|
||||
return -1;
|
||||
}
|
||||
if (WIFEXITED(ws) && !WEXITSTATUS(ws)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int PrintBacktrace(int fd, const struct StackFrame *bp) {
|
||||
|
|
|
@ -50,7 +50,6 @@ int PrintBacktraceUsingSymbols(int fd, const struct StackFrame *bp,
|
|||
char buf[256], ibuf[21];
|
||||
const struct Symbol *symbol;
|
||||
const struct StackFrame *frame;
|
||||
if (!st) return -1;
|
||||
if (!bp) bp = __builtin_frame_address(0);
|
||||
garbage = weaken(__garbage);
|
||||
gi = garbage ? garbage->i : 0;
|
||||
|
@ -66,8 +65,9 @@ int PrintBacktraceUsingSymbols(int fd, const struct StackFrame *bp,
|
|||
*p++ = ' ';
|
||||
p = mempcpy(p, ibuf, uint64toarray_fixed16(addr, ibuf, 48));
|
||||
*p++ = ' ';
|
||||
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
|
||||
(intptr_t)addr <= (intptr_t)&_end)) {
|
||||
if (st && st->count &&
|
||||
((intptr_t)addr >= (intptr_t)&_base &&
|
||||
(intptr_t)addr <= (intptr_t)&_end)) {
|
||||
symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
|
||||
st->count, addr - st->addr_base - 1)];
|
||||
p = stpcpy(p, &st->name_base[symbol->name_rva]);
|
||||
|
|
|
@ -56,10 +56,10 @@ relegated void __check_fail(const char *suffix, const char *opstr,
|
|||
gethostname(hostname, sizeof(hostname));
|
||||
|
||||
(dprintf)(STDERR_FILENO,
|
||||
"check failed on %s pid %d\r\n"
|
||||
"\tCHECK_%s(%s, %s);\r\n"
|
||||
"\t\t → %#lx (%s)\r\n"
|
||||
"\t\t%s %#lx (%s)\r\n",
|
||||
"check failed on %s pid %d\n"
|
||||
"\tCHECK_%s(%s, %s);\n"
|
||||
"\t\t → %#lx (%s)\n"
|
||||
"\t\t%s %#lx (%s)\n",
|
||||
hostname, getpid(), sufbuf, wantstr, gotstr, want, wantstr, opstr,
|
||||
got, gotstr);
|
||||
|
||||
|
@ -68,19 +68,19 @@ relegated void __check_fail(const char *suffix, const char *opstr,
|
|||
va_start(va, fmt);
|
||||
(vdprintf)(STDERR_FILENO, fmt, va);
|
||||
va_end(va);
|
||||
(dprintf)(STDERR_FILENO, "\r\n");
|
||||
(dprintf)(STDERR_FILENO, "\n");
|
||||
}
|
||||
|
||||
(dprintf)(STDERR_FILENO, "\t%s\r\n\t%s%s%s%s\r\n", strerror(lasterr), SUBTLE,
|
||||
(dprintf)(STDERR_FILENO, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE,
|
||||
getauxval(AT_EXECFN), g_argc > 1 ? " \\" : "", RESET);
|
||||
|
||||
for (i = 1; i < g_argc; ++i) {
|
||||
(dprintf)(STDERR_FILENO, "\t\t%s%s\r\n", g_argv[i],
|
||||
(dprintf)(STDERR_FILENO, "\t\t%s%s\n", g_argv[i],
|
||||
i < g_argc - 1 ? " \\" : "");
|
||||
}
|
||||
|
||||
if (!IsTiny() && lasterr == ENOMEM) {
|
||||
(dprintf)(STDERR_FILENO, "\r\n");
|
||||
(dprintf)(STDERR_FILENO, "\n");
|
||||
PrintMemoryIntervals(STDERR_FILENO, &_mmi);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,5 +46,5 @@ relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
|
|||
__print(bx, uint64toarray_radix16(got, bx));
|
||||
__print_string(" (");
|
||||
__print(bx, int64toarray_radix10(lasterr, bx));
|
||||
__print_string(")\r\n");
|
||||
__print_string(")\n");
|
||||
}
|
||||
|
|
|
@ -18,13 +18,21 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Writes error messages to standard error.
|
||||
*/
|
||||
void perror(const char *message) {
|
||||
fprintf(stderr, "%s%s%s: %s: %s: %s\r\n", RED2, "error", RESET,
|
||||
program_invocation_name, strerror(errno), message);
|
||||
int err;
|
||||
err = errno;
|
||||
if (message && *message) {
|
||||
fputs(message, stderr);
|
||||
fputs(": ", stderr);
|
||||
}
|
||||
fputs(strerror(err), stderr);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,9 @@ STATIC_YOINK("ntoa");
|
|||
STATIC_YOINK("stoa");
|
||||
STATIC_YOINK("ftoa");
|
||||
|
||||
static int loglevel2char(unsigned level) {
|
||||
static struct timespec vflogf_ts;
|
||||
|
||||
static int vflogf_loglevel2char(unsigned level) {
|
||||
switch (level) {
|
||||
case kLogInfo:
|
||||
return 'I';
|
||||
|
@ -78,34 +80,46 @@ void vflogf_onfail(FILE *f) {
|
|||
|
||||
/**
|
||||
* Writes formatted message w/ timestamp to log.
|
||||
*
|
||||
* Timestamps are hyphenated out when multiple events happen within the
|
||||
* same second in the same process. When timestamps are crossed out, it
|
||||
* will display microseconsd as a delta elapsed time. This is useful if
|
||||
* you do something like:
|
||||
*
|
||||
* LOGF("connecting to foo");
|
||||
* connect(...)
|
||||
* LOGF("connected to foo");
|
||||
*
|
||||
* In that case, the second log entry will always display the amount of
|
||||
* time that it took to connect. This is great in forking applications.
|
||||
*/
|
||||
void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
||||
const char *fmt, va_list va) {
|
||||
static struct timespec ts;
|
||||
struct tm tm;
|
||||
long double t2;
|
||||
const char *prog;
|
||||
int64_t secs, nsec, dots;
|
||||
bool issamesecond;
|
||||
char buf32[32], *buf32p;
|
||||
int64_t secs, nsec, dots;
|
||||
if (!f) f = g_logfile;
|
||||
if (fileno(f) == -1) return;
|
||||
t2 = nowl();
|
||||
secs = t2;
|
||||
nsec = rem1000000000int64(t2 * 1e9L);
|
||||
if (secs > ts.tv_sec) {
|
||||
nsec = (t2 - secs) * 1e9L;
|
||||
issamesecond = secs == vflogf_ts.tv_sec;
|
||||
dots = issamesecond ? nsec - vflogf_ts.tv_nsec : nsec;
|
||||
vflogf_ts.tv_sec = secs;
|
||||
vflogf_ts.tv_nsec = nsec;
|
||||
if (!issamesecond) {
|
||||
localtime_r(&secs, &tm);
|
||||
strftime(buf32, sizeof(buf32), "%Y-%m-%dT%H:%M:%S.", &tm);
|
||||
buf32p = buf32;
|
||||
dots = nsec;
|
||||
} else {
|
||||
buf32p = "--------------------";
|
||||
dots = nsec - ts.tv_nsec;
|
||||
}
|
||||
ts.tv_sec = secs;
|
||||
ts.tv_nsec = nsec;
|
||||
prog = basename(program_invocation_name);
|
||||
if ((fprintf)(f, "%c%s%06ld:%s:%d:%.*s:%d] ", loglevel2char(level), buf32p,
|
||||
rem1000000int64(div1000int64(dots)), file, line,
|
||||
if ((fprintf)(f, "%c%s%06ld:%s:%d:%.*s:%d] ", vflogf_loglevel2char(level),
|
||||
buf32p, rem1000000int64(div1000int64(dots)), file, line,
|
||||
strchrnul(prog, '.') - prog, prog, getpid()) <= 0) {
|
||||
vflogf_onfail(f);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue