From 4b1c3d8e3ffa7af27f8b3f69aa69d91316357a84 Mon Sep 17 00:00:00 2001 From: Anachronaut Date: Thu, 3 Sep 2026 15:50:40 -0400 Subject: [PATCH] A missing file is an error, not a core dump Naming a pad file that is not there printed the error and then said the machine had STARTED. MACHINE_OK is nought and the code returned nought, so the front end ran a machine whose clock had never been set up and divided by it: a typo in a path came out as a floating point exception and a core dump. The trap is two functions in one file with opposite conventions - machineStart returns MACHINE_OK for worked, machineRestart thirty lines up returns 1 for worked - and this copied the nearer one. Both of the returns I added last week had it. Checked now for all three files the replay suite is about, because the same mistake fits all of them, and re-broken to be sure: the check comes back exit 136, which is a signal 8, which is the crash. Found by somebody typing a path that was not there, which is the fourth thing this week that no test would have reached. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW --- Source/Emulator/machine.c | 13 +++++++++++-- Tests/replay.sh | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Source/Emulator/machine.c b/Source/Emulator/machine.c index dd81d68..ce2f867 100644 --- a/Source/Emulator/machine.c +++ b/Source/Emulator/machine.c @@ -225,6 +225,15 @@ uint8_t machineStart(Machine *m, const EmulatorOptions *options, const char *pro } // ---- The pads, from files ---- // + // MACHINE_ERROR and not nought. Nought is MACHINE_OK here, so returning it after printing + // an error said the machine had started - and the front end then ran a machine whose + // clock had never been set up and divided by it. A missing file came out as a floating + // point exception and a core dump. + // + // The trap is that machineRestart, thirty lines up, returns 1 for worked and 0 for did + // not. Two functions in one file with opposite conventions, and this copied the nearer + // one. + // // Opened here beside the keyboard because they are the same kind of thing: a recording // standing in for a person, so that what a person would exercise is reachable from a // suite. They are never closed, for the same reason the keyboard is not - the machine @@ -233,7 +242,7 @@ uint8_t machineStart(Machine *m, const EmulatorOptions *options, const char *pro FILE *pad = fopen(options->pads[n], "rb"); if (pad == NULL) { fprintf(stderr, "Error: Couldn't open pad file: %s\n", options->pads[n]); - return 0; + return MACHINE_ERROR; } padFromFile(n, pad); } @@ -242,7 +251,7 @@ uint8_t machineStart(Machine *m, const EmulatorOptions *options, const char *pro FILE *pad = fopen(options->padRecord, "wb"); if (pad == NULL) { fprintf(stderr, "Error: Couldn't write pad file: %s\n", options->padRecord); - return 0; + return MACHINE_ERROR; } padRecordTo(pad); } diff --git a/Tests/replay.sh b/Tests/replay.sh index 3759124..70103ff 100755 --- a/Tests/replay.sh +++ b/Tests/replay.sh @@ -114,6 +114,30 @@ print('yes' if set(data) <= {0} else 'no') && result ok "and nothing held is written as nothing" "no buttons nobody pressed" \ || result no "and nothing held is written as nothing" "the recording holds something" +# ---- A file that is not there is an error, not a crash ---- +# +# Naming a pad file that does not exist used to print the error and then say the machine had +# STARTED: MACHINE_OK is nought, and the code returned nought. The front end then ran a +# machine whose clock had never been set up and divided by it, so a typo in a path came out as +# a floating point exception and a core dump. +# +# The trap was two functions in one file with opposite conventions - machineRestart returns 1 +# for worked - and the wrong neighbour being copied. Checked here for all three files this +# suite is about, because the same mistake fits all of them. +for missing in "--pad" "--keyboard" "--record-pad"; do + case "$missing" in + --record-pad) where="/nowhere/at/all.pad" ;; + *) where="$BUILD/there-is-no-such-file" ;; + esac + "$EMU" $missing "$where" "$BUILD/padTest.bin" > "$BUILD/missing.out" 2>&1 + status=$? + if [ "$status" = "1" ] && grep -q "Error:" "$BUILD/missing.out"; then + result ok "$missing with no file stops cleanly" "an error and a status, not a signal" + else + result no "$missing with no file stops cleanly" "exit $status" + fi +done + echo if [ "$FAIL" -eq 0 ]; then echo "All $PASS replay checks passed."