Skip to content

fix: harden macOS support and shorten the README - #68

Merged
Reddimus merged 2 commits into
mainfrom
fix/macos-readme
Sep 25, 2026
Merged

Reddimus merged 2 commits into
mainfrom
fix/macos-readme

Conversation

@Reddimus

@Reddimus Reddimus commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Summary

This makes macOS support explicit and tested, and shortens the README.

  • SIGPIPE. A connection the peer resets can no longer end the process. WebSocketClient relied on libwebsockets calling signal(SIGPIPE, SIG_IGN) process-wide, and an app that restores the default handler undoes that. OpenSSL sends with plain write(), so MSG_NOSIGNAL never applied to wss://. Two mechanisms are needed, because the kernels differ:

    • macOS and the BSDs send a write's SIGPIPE to the whole process, so each socket sets SO_NOSIGPIPE in LWS_CALLBACK_CONNECTING.
    • Linux sends it to the writing thread, so the network thread blocks SIGPIPE.

    Tests check the socket option and the thread mask. An end-to-end run uses a real client against a local wss server that resets every connection, with SIGPIPE at its default. The earlier mask-only build dies with exit 141 on macOS. This build survives 23 resets on both macOS and Ubuntu 24.04.

  • macOS 13.3 minimum. std::to_chars(double) needs it: a 13.2 build fails only on that call in src/api/support.cpp. The README now states the minimum, and the macOS CI job builds at CMAKE_OSX_DEPLOYMENT_TARGET=13.3. The linker warns that Homebrew's dylibs target 26.0; that's expected.

  • KALSHI_NATIVE_ARCH now probes -march=native on every configure and stops with a clear message when the compiler rejects it for the target. That covers universal builds, CMAKE_OSX_ARCHITECTURES=x86_64, and CMAKE_APPLE_SILICON_PROCESSOR=x86_64. Before, the build failed partway through with unknown target CPU 'apple-m4'.

  • Tools. make lint, make format, and make tidy find Homebrew's keg-only llvm@18, so CONTRIBUTING drops its CLANG_FORMAT export.

  • Benchmarks (macOS). allocs no longer counts the allocation made by recording the instructions counter. This came up in the review of test(bench): count allocations and use realistic fixtures #65.

  • README. It's shorter. Result/std::expected moves from the intro into a short Errors section after the first example, and the setup names the tested platforms. The repo description will drop std::expected too; I'll update it after merge.

No Intel macOS CI job: Homebrew has stopped building Intel bottles, and the Linux and Windows jobs already cover x86_64 code generation. Instead, I built an x86_64 slice once, locally under Rosetta, with vcpkg x64-osx dependencies (Glaze 8.4). All 282 tests passed.

Checks

  • make format lint test (282 tests), with the stock PATH finding llvm@18
  • make sanitize, make tsan, make tidy, ./tools/test_consumers.sh, make docs
  • Built at macOS 13.3, which passes, and 13.2, which fails only on to_chars as expected. Ran the KALSHI_NATIVE_ARCH probe with arm64;x86_64, x86_64, CMAKE_APPLE_SILICON_PROCESSOR=x86_64, a preset CMAKE_SYSTEM_NAME, and the host.
  • README snippets compile with -Wall -Wextra -Wpedantic -Werror; markdownlint clean
  • Ubuntu 24.04 replica: build, sanitize, tsan, tidy, docs
  • Two review rounds with adversarial verification: first this PR, then everything since v0.6.1. Every confirmed finding is fixed in the later commits.
  • CHANGELOG.md updated under [Unreleased]
  • SemVer impact: patch

Copilot AI lite review requested due to automatic review settings September 25, 2026 20:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

- WebSocketClient's network thread blocks SIGPIPE. OpenSSL sends with
  write(), so a reset peer raised SIGPIPE on every POSIX platform once an
  application restored the default handler that libwebsockets turns off.
- KALSHI_NATIVE_ARCH probes -march=native at configure time and stops when
  the compiler rejects it for the target, as universal builds do.
- make lint/format/tidy find Homebrew's keg-only llvm@18.
- CI builds macOS against 13.3, the minimum deployment target that
  std::to_chars(double) requires.
- README is shorter: an Errors section explains Result/std::expected after
  the first example, and the setup states the tested platforms.
…h probe

Review of everything since v0.6.1:
- macOS and the BSDs send a write's SIGPIPE to the whole process, so the
  network thread's mask protected only Linux. Sockets now also set
  SO_NOSIGPIPE in LWS_CALLBACK_CONNECTING where the OS defines it. A local
  wss server that resets connections killed the mask-only build with
  SIGPIPE; the fixed build survives on macOS and Linux.
- check_cxx_compiler_flag cached the -march=native result, so a reconfigure
  with different architectures reused a stale answer.
- LoopReport counted the allocation made by recording the instructions
  counter on macOS.
@Reddimus
Reddimus merged commit b64a44d into main Sep 25, 2026
14 checks passed
@Reddimus
Reddimus deleted the fix/macos-readme branch September 25, 2026 22:20
@Reddimus Reddimus mentioned this pull request Sep 25, 2026
4 tasks done
Reddimus added a commit that referenced this pull request Sep 25, 2026
## Summary

Releases 0.6.2: sets the CMake version, moves the `[Unreleased]` notes
into a `[0.6.2]` section, adds its compare links, and points the
README's FetchContent example at `v0.6.2`.

0.6.2 contains #65 (allocation and instruction counters in the
benchmarks, with realistic fixtures), #67 (`RateLimitedTransport` stays
inside the batch body and no longer copies each order: 26 allocations
down to 6 for 20 orders), and #68 (SIGPIPE protection, macOS build
fixes, and the shorter README). No public API changes.

After this merges, tagging `v0.6.2` on the merge commit runs
`release.yml`. It checks the tag against the CMake version and the
CHANGELOG section, waits for CI on that commit, publishes the release,
and dispatches the API reference deploy to GitHub Pages.

## Checks

- [x] `tools/project_version.sh` prints 0.6.2
- [x] `release.yml`'s extraction of the `[0.6.2]` section yields the
notes
- [x] `make lint-docs` and `./tools/test_consumers.sh` pass
- [x] SemVer impact: this is the 0.6.2 patch release
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants