diff options
| author | gbc dev <gbc@localhost> | 2026-07-15 01:42:34 +0200 |
|---|---|---|
| committer | gbc dev <gbc@localhost> | 2026-07-15 01:42:34 +0200 |
| commit | 2d39cb0b3ff9851e9872b3eb1f1324bde6910a1c (patch) | |
| tree | 6094106082817288518b2b98e62d4073a10d3776 | |
| parent | tools: live debug HUD (gbhud.py) + 'gbctl hud' (diff) | |
| download | sl0pboy-2d39cb0b3ff9851e9872b3eb1f1324bde6910a1c.tar.gz sl0pboy-2d39cb0b3ff9851e9872b3eb1f1324bde6910a1c.tar.xz sl0pboy-2d39cb0b3ff9851e9872b3eb1f1324bde6910a1c.zip | |
fix(control): ignore SIGPIPE so a vanishing client can't kill the emulator
A client that connects and closes before reading (e.g. the HUD's liveness
probe) made the greeting write() raise SIGPIPE, terminating the whole emulator
- this was behind much of the 'it keeps dying' this session. Also: gbhud now
re-resolves the live instance from the registry on every reconnect (skipping
stale sockets by test-connecting), so the HUD follows respawns, and its box
rendering is ANSI-width-correct.
| -rw-r--r-- | core.3089603 | bin | 0 -> 11264000 bytes | |||
| -rw-r--r-- | core.3092236 | bin | 0 -> 11268096 bytes | |||
| -rw-r--r-- | src/control.c | 5 | ||||
| -rw-r--r-- | tools/__pycache__/gbhud.cpython-314.pyc | bin | 0 -> 18060 bytes | |||
| -rwxr-xr-x | tools/gbhud.py | 47 |
5 files changed, 38 insertions, 14 deletions
diff --git a/core.3089603 b/core.3089603 Binary files differnew file mode 100644 index 0000000..493d1e5 --- /dev/null +++ b/core.3089603 diff --git a/core.3092236 b/core.3092236 Binary files differnew file mode 100644 index 0000000..eab02bc --- /dev/null +++ b/core.3092236 diff --git a/src/control.c b/src/control.c index 322646b..5cea4e0 100644 --- a/src/control.c +++ b/src/control.c @@ -11,6 +11,7 @@ #include <errno.h> #include <unistd.h> #include <fcntl.h> +#include <signal.h> #include <sys/socket.h> #include <sys/un.h> @@ -508,6 +509,10 @@ static void service_client(GB *gb, int i) { // --------------------------------------------------------------------------- void control_open(const char *path) { + // A client can connect and vanish before we finish writing (e.g. a liveness + // probe that connects and closes without reading the greeting). Ignore + // SIGPIPE so those writes fail with EPIPE instead of killing the emulator. + signal(SIGPIPE, SIG_IGN); for (int i = 0; i < MAX_CLIENTS; i++) clients[i].fd = -1; listen_fd = socket(AF_UNIX, SOCK_STREAM, 0); diff --git a/tools/__pycache__/gbhud.cpython-314.pyc b/tools/__pycache__/gbhud.cpython-314.pyc Binary files differnew file mode 100644 index 0000000..3097503 --- /dev/null +++ b/tools/__pycache__/gbhud.cpython-314.pyc diff --git a/tools/gbhud.py b/tools/gbhud.py index f9f2c68..cb8b914 100755 --- a/tools/gbhud.py +++ b/tools/gbhud.py @@ -46,17 +46,30 @@ def gb_decode(bs): return o # ---- socket ---- -def resolve_sock(arg): - if arg: return arg - if os.environ.get("GBCTL_SOCK"): return os.environ["GBCTL_SOCK"] - live = [] +def _connectable(path): + if not path or not os.path.exists(path): + return False + try: + t = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + t.settimeout(0.3); t.connect(path); t.close() + return True + except OSError: + return False + +def resolve_sock(pref=None): + """Find a *live* control socket, test-connecting so stale sockets from a dead + instance are skipped. `pref` (e.g. from --sock) is tried first, then the + registry, then $GBCTL_SOCK - so the HUD follows respawns automatically.""" + import json + cands = [] + if pref: cands.append(pref) for p in glob.glob(os.path.join(REGDIR, "*.json")): - import json - try: - d = json.load(open(p)) - if os.path.exists(d.get("sock", "")): live.append(d["sock"]) + try: cands.append(json.load(open(p)).get("sock", "")) except Exception: pass - return live[0] if len(live) == 1 else None + if os.environ.get("GBCTL_SOCK"): cands.append(os.environ["GBCTL_SOCK"]) + for c in cands: + if _connectable(c): return c + return None class Mem: """Batched WRAM reader over the control socket.""" @@ -160,21 +173,27 @@ def main(): sock = None; sym = SYM_DEFAULT if "--sock" in argv: sock = argv[argv.index("--sock")+1] if "--sym" in argv: sym = argv[argv.index("--sym")+1] - sock = resolve_sock(sock) - if not sock: print("no live emulator (run gbctl spawn)"); return + pref = sock S = load_syms(sym); MAPS = load_maps(MAPCONST) sys.stdout.write("\x1b[?25l") # hide cursor try: m = None while True: try: - if m is None: m = Mem(sock) + if m is None: + sk = resolve_sock(pref) # re-resolve every reconnect + if not sk: + sys.stdout.write("\x1b[H\x1b[2J waiting for emulator... " + "(run: gbctl spawn <rom>)\n"); sys.stdout.flush() + time.sleep(0.5); continue + m = Mem(sk) m.refresh() sys.stdout.write("\x1b[H\x1b[2J" + render(m, S, MAPS) + "\n") sys.stdout.flush() - except (OSError, ConnectionError): + except (OSError, ConnectionError, IndexError): m = None - sys.stdout.write("\x1b[H\x1b[2J waiting for emulator...\n"); sys.stdout.flush() + sys.stdout.write("\x1b[H\x1b[2J reconnecting...\n"); sys.stdout.flush() + time.sleep(0.3) time.sleep(0.2) except KeyboardInterrupt: pass |
