99 lines
2.6 KiB
C
99 lines
2.6 KiB
C
// Cross-platform "where did it hang?" logger. Holds joeylog.txt open
|
|
// across calls; libc's stdio buffer absorbs writes (~4 KB) and the
|
|
// final fclose at program exit (via atexit) gets the buffer to disk.
|
|
//
|
|
// Earlier rev opened+closed per call for crash durability ("last line
|
|
// guaranteed on disk if we hang"); that cost ~1 second per call
|
|
// through GoldenGate's ProDOS FST emulation -- a 50-line UBER run
|
|
// burned ~5 minutes in IO. Even per-line fflush is too expensive
|
|
// because every fflush forces an FST WRITE, and host-OS file IO time
|
|
// isn't tracked by the IIgs VBL counter so wall-time logs underreport.
|
|
//
|
|
// Tradeoff: if the program crashes mid-run, buffered log lines may
|
|
// not reach disk. For UBER and similar batch demos that's acceptable;
|
|
// for hang-debugging where durability matters, call joeyLogFlush()
|
|
// at the suspected hang points.
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "joey/platform.h"
|
|
#include "joey/debug.h"
|
|
|
|
|
|
static const char *kLogPath = "joeylog.txt";
|
|
static FILE *gLogFp = NULL;
|
|
/* 16 KB is enough for UBER's full log (~5 KB) plus generous headroom,
|
|
* so the file never auto-flushes mid-run. ORCA-C / libnix default
|
|
* buffers are only ~512 bytes; with that, a 50-line log triggers ~10
|
|
* ProDOS / AmigaDOS WRITEs through the host FST, each of which is
|
|
* untracked-host-time (seconds). Buffer the whole thing in memory and
|
|
* let the atexit fclose flush once. */
|
|
#define JOEY_LOG_BUF_BYTES 16384
|
|
static char gLogBuf[JOEY_LOG_BUF_BYTES];
|
|
|
|
|
|
/* Lazy-open. Returns NULL if the open failed (silently disable). */
|
|
static FILE *logFile(void) {
|
|
if (gLogFp == NULL) {
|
|
gLogFp = fopen(kLogPath, "a");
|
|
if (gLogFp != NULL) {
|
|
(void)setvbuf(gLogFp, gLogBuf, _IOFBF, sizeof(gLogBuf));
|
|
}
|
|
}
|
|
return gLogFp;
|
|
}
|
|
|
|
|
|
void joeyLog(const char *msg) {
|
|
FILE *fp;
|
|
if (msg == NULL) {
|
|
return;
|
|
}
|
|
fp = logFile();
|
|
if (fp == NULL) {
|
|
return;
|
|
}
|
|
fputs(msg, fp);
|
|
fputc('\n', fp);
|
|
}
|
|
|
|
|
|
void joeyLogF(const char *fmt, ...) {
|
|
FILE *fp;
|
|
va_list args;
|
|
if (fmt == NULL) {
|
|
return;
|
|
}
|
|
fp = logFile();
|
|
if (fp == NULL) {
|
|
return;
|
|
}
|
|
va_start(args, fmt);
|
|
vfprintf(fp, fmt, args);
|
|
va_end(args);
|
|
fputc('\n', fp);
|
|
}
|
|
|
|
|
|
void joeyLogFlush(void) {
|
|
if (gLogFp != NULL) {
|
|
fflush(gLogFp);
|
|
}
|
|
}
|
|
|
|
|
|
void joeyLogReset(void) {
|
|
if (gLogFp != NULL) {
|
|
fclose(gLogFp);
|
|
gLogFp = NULL;
|
|
}
|
|
/* Truncate by opening for write then closing; subsequent
|
|
* joeyLog* will reopen for append. */
|
|
{
|
|
FILE *fp = fopen(kLogPath, "w");
|
|
if (fp != NULL) {
|
|
fclose(fp);
|
|
}
|
|
}
|
|
}
|