release: sync develop into master - #9
Merged
Merged
Conversation
Add logserver.h / logserver.m that binds 0.0.0.0:18082 in debug builds (FINAL_RELEASE undefined). Operators can tail live logs from any PC on the same network with `nc <device-ip> 18082` — no SSH or Files.app needed. - logserver.h: public API (IPALogServerStart / IPALogServerPush) - logserver.m: dispatch-queue serial server, fans out to up to IPA_LOG_SERVER_MAX_CLIENTS (4) simultaneous readers - logging.m: call IPALogServerStart() in IPALoggingInit() and IPALogServerPush() in IPALog(), both guarded by #ifndef FINAL_RELEASE - logging.h: document the new debug destination in the header comment FINAL_RELEASE=1 strips the entire TCP sink at compile time, leaving the existing NSLog / os_log / sandbox-file destinations untouched. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
add nc <device-ip> 18082 tail example and note that FINAL_RELEASE compiles the stream out
…#3) Cross-tweak reference for picking the right cave shape and wiring both sides correctly. Until now the observer / entry split lived only as folklore in consumer recipes (Bridge, KiouForge); writing it down here keeps Chinlan as the canonical source for the cross-tweak contract that the runtime's IPAChinlanResolveOrig already implies. - docs/CAVES.md (new): * Kinds at a glance — capability matrix covering override return, register substitution, W6 clobber, shared dispatcher vs per-site slot. * Decision flow — when observer is enough and when entry is required. * Annotated 21-insn / 84-byte layouts side-by-side so the +0x4C bypass-entry contract that both kinds preserve is obvious. * End-to-end recipe / hook / dispatcher examples for both kinds plus an entry-cave argument-substitution variant. * Common pitfalls — W6 clobber, cave-order vs bypass-index coupling, bss locality requirement for entry slot tables, the KIOU_CALL_ORIG_RET-drops-varargs trap on chinlan builds. - README.md: short "Cave kinds" section pointing at the new page so consumers landing on the repo top see the link without scrolling. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
) Replaces the previous "single append-only <tag>.log" with a size-bounded rotation scheme so a long-running consumer can't fill the sandbox with a multi-GB log. - Files now live under <base>/Logs/ (created on init), so an operator can grab the whole rotated set (<tag>.log + <tag>.{1..N-1}.log) by copying one directory instead of fishing individual files out. PascalCase matches iOS's own sandbox conventions (Documents/, Library/, etc.). Base stays the existing tmp/ or, with IPA_LOG_TO_DOCUMENTS=1, the Files.app-visible Documents/. - IPALogPath samples the current size every IPA_LOG_ROTATE_CHECK_EVERY writes (default 64) and, once it crosses IPA_LOG_MAX_BYTES (default 4 MiB), shifts <tag>.log -> <tag>.1.log -> ... -> <tag>.{N-1}.log, dropping anything past N-1. N defaults to 3 generations (so up to 12 MiB on disk per consumer at the default ceiling). - All three knobs (max bytes, generation count, sample interval) are -D overridable at build time so a noisy consumer can dial up retention without forking this file. Best-effort throughout: failed mkdir falls back to writing into the parent directory, and rotation runs without an explicit lock — the sampling cadence already keeps two concurrent writers from both rotating in the same window, and a stray double-rotate just produces an empty .1.log instead of corrupting data. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Three review nits from #3 plus one extra ABI wording fix: - Unify the ADRP/LDR placeholder names in both cave diagrams. The pair previously read `page(HOOK_SLOT_RVA) + lo12(SLOT)` and `page(entry_slot_va) + lo12(slot)`; using two names for the same address obscures the relocation pattern. - Fix the inline code that was broken across a hard line wrap (`-Werror=unused-` / `variable`) so Markdown actually renders the flag as code instead of opening an unterminated backtick span. - Tighten the AAPCS64 wording: W9 isn't an arg-9 slot. The integer argument sequence ends at x7, x8 is the indirect-result register, and x9–x15 are call-clobbered scratch — which is exactly why touching W9 from the entry cave is safe. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
When a client connects to the TCP log server, it now receives the last IPA_LOG_REPLAY_BYTES (default 100 KB) of the sandbox log file before switching to the live stream. This avoids the race where logs written at process startup — including login-time crashes — are lost because no nc session was open yet. Implementation: - ls_replay_to(fd): opens the log file, seeks to max(0, size - 100KB), skips to the next newline to avoid a partial first line, then streams the remainder synchronously before the client is admitted to g_clients[]. - IPALogServerSetReplayPath(NSString *): dispatched onto g_queue so g_replayPath access stays single-threaded. - IPALoggingInit() calls IPALogServerSetReplayPath(g_logSandbox) once the path is finalised (after IPALogServerStart, before first IPALog). - Knob: -D IPA_LOG_REPLAY_BYTES=N to override at build time. - No change to FINAL_RELEASE builds (replay code compiled out with the rest of logserver). Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Promotes develop into master, bringing in recent runtime logging improvements, new cave-layout documentation, and a CI guard to enforce the develop→master release flow.
Changes:
- Add a debug-only LAN TCP log streaming server with optional “replay tail on connect”.
- Update sandbox file logging to write under a
Logs/subdirectory and rotate files by size. - Add master-PR source-branch guard in CI and expand documentation (README + new
docs/CAVES.md).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents the new TCP log stream + cave kinds and build flags. |
| logserver.m | Implements the debug-only TCP log streaming server with client fanout and replay. |
| logserver.h | Declares the debug-only logserver API (compiled out under FINAL_RELEASE). |
| logging.m | Adds log rotation + Logs/ subdir handling and forwards logs to the TCP stream in non-final builds. |
| logging.h | Documents the debug-only TCP stream behavior. |
| docs/CAVES.md | Adds detailed documentation for observer vs entry cave shapes and wiring. |
| .github/workflows/integration.yaml | Adds CI job rejecting PRs to master unless the source branch is develop. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
147
to
+149
| | `IPA_JAILED` | `hookengine.h` uses Dobby (statically linked) instead of `libsubstrate`. | | ||
| | `IPA_LOG_TO_DOCUMENTS` | `logging.m` writes the file log to `<sandbox>/Documents/<tag>.log` instead of `tmp/`. | | ||
| | `FINAL_RELEASE` | `logging.m` / `logserver.m` remove the LAN TCP log stream entirely; only NSLog, `os_log`, and the sandbox file sink remain. | |
Comment on lines
+64
to
+68
| every log line to NSLog, `os_log` (subsystem-scoped), an append-only | ||
| file inside the app sandbox, and — when `FINAL_RELEASE` is not defined — | ||
| a LAN-visible TCP log stream on `0.0.0.0:18082`. `IPA_LOG_TO_DOCUMENTS=1` | ||
| at build time routes the file destination to `<sandbox>/Documents/` so | ||
| Files.app can read it on a non-jailbroken device. The TCP stream can be |
Comment on lines
+112
to
+115
| static void IPAMaybeRotate(NSString *path) { | ||
| unsigned n = atomic_fetch_add_explicit(&g_writeCount, 1, memory_order_relaxed); | ||
| if ((n % IPA_LOG_ROTATE_CHECK_EVERY) != 0) return; | ||
|
|
Comment on lines
+83
to
+96
| // Send all bytes to fd. Returns NO and closes fd on any error. | ||
| static BOOL ls_send_all(int fd, const uint8_t *buf, size_t len) { | ||
| size_t off = 0; | ||
| while (off < len) { | ||
| ssize_t n = send(fd, buf + off, len - off, 0); | ||
| if (n < 0) { | ||
| if (errno == EINTR) continue; | ||
| return NO; | ||
| } | ||
| if (n == 0) return NO; | ||
| off += (size_t)n; | ||
| } | ||
| return YES; | ||
| } |
Comment on lines
+217
to
+221
| int s = socket(AF_INET, SOCK_STREAM, 0); | ||
| if (s < 0) { | ||
| IPALog([NSString stringWithFormat:@"[LOGSVR] socket errno=%d", errno]); | ||
| return; | ||
| } |
Comment on lines
+230
to
+235
| if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { | ||
| IPALog([NSString stringWithFormat:@"[LOGSVR] bind errno=%d port=%u", | ||
| errno, (unsigned)port]); | ||
| close(s); | ||
| return; | ||
| } |
Comment on lines
+236
to
+240
| if (listen(s, IPA_LOG_SERVER_MAX_CLIENTS) < 0) { | ||
| IPALog([NSString stringWithFormat:@"[LOGSVR] listen errno=%d", errno]); | ||
| close(s); | ||
| return; | ||
| } |
tkgstrator
added a commit
that referenced
this pull request
Jul 27, 2026
release: sync develop into master
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promote develop → master, including:
🤖 Generated with Claude Code