Skip to content

0.2.0

Latest

Choose a tag to compare

@adamtheturtle adamtheturtle released this 18 Jul 17:51
2671b72

Crash and data-loss fixes. Each was reproduced before being fixed, and each carries a regression test verified to fail without it.

Fixed

  • intArgument no longer crashes the server on an out-of-range number (#2). A JSON number outside Int's range arrives as .double, and Int(_: Double) traps — so an unprivileged client could kill the process with one tool call. Now returns nil, as documented, while keeping the documented truncating behaviour for in-range doubles.
  • jsonResult no longer aborts on NaN or non-JSON values (#3). JSONSerialization raises an Objective-C NSException, which try? cannot catch, so the documented error path was unreachable. Guarded with isValidJSONObject(_:).
  • JSONLLog.append is now atomic (#4). The log opened O_WRONLY without O_APPEND and did seek-then-write — a lost-update race. Measured before the fix: 4 concurrent writers × 500 appends lost 364 entries and tore 162 lines. Now opens O_WRONLY|O_APPEND|O_CREAT, so the kernel positions each write.
  • One invalid UTF-8 byte no longer empties the whole log (#5). Reading via String(contentsOf:encoding:) failed for the entire file on a single bad byte — which the append race above produced — making the log read as empty and trim() a permanent no-op. Lines are now split on 0x0A and decoded individually, delivering the tolerance the API already promised.
  • A failed open no longer destroys the log (#6). The fallback branch assumed "file doesn't exist", but also fired on EACCES, and its atomic write renamed over the target — replacing the entire history. Verified before the fix: chmod 444 plus one append reduced a 4-entry log to 1 entry.
  • runOverStdioUntilExit no longer deadlocks a @MainActor provider (#7). The semaphore blocked the main thread, which is the main actor's executor, so any provider touching main-actor state hung forever on tools/call with no error. The main thread now goes to dispatchMain(), keeping the main actor live.

Upgrading

intArgument returns nil instead of trapping for out-of-range, NaN, and infinite values, and "3.9" now coerces to 3 for consistency with 3.9. runOverStdioUntilExit no longer returns control by blocking; behaviour off the main thread is unchanged.

Full changelog: 0.1.0...0.2.0