Skip to main content
macOS TCP Time Bomb: 49 Days Uptime = Networking Meltdown
🖥️ Infrastructure

macOS TCP Time Bomb: 49 Days Uptime = Networking Meltdown

// TIME: 7 min read AUTH: Richard Soutar
macostcpxnu-kernelinteger-overflowdevopsnetworking

Picture this: Your fleet of Mac minis has been humming along perfectly for weeks. Monitoring dashboards green, iMessage pings flying, everything chill. Then one random Tuesday… new TCP connections just stop. Ping still works. Existing sockets? Fine. But good luck opening anything new. Ephemeral ports? Exhausted. The machines are basically network zombies.

Welcome to the macOS 49.7-day TCP time bomb. We didn’t build it, but Apple baked it right into the XNU kernel. And yes, it detonates exactly after 49 days, 17 hours, 2 minutes, and 47-ish seconds of continuous uptime.

(Shoutout to Photon for the epic deep dive that exposed this beauty.)

The Setup: Why TIME_WAIT Even Exists

TCP is polite but paranoid. When you close a connection, it hangs out in TIME_WAIT for a bit (on macOS: 2 × MSL = 30 seconds). This prevents late-arriving packets from confusing the next guy who reuses the same port.

Normally, the kernel cleans these up like a diligent janitor. But what if the janitor’s watch stops ticking?

The Bug: 32-Bit Unsigned Integer Goes Boom

Deep in the XNU kernel (bsd/netinet/tcp_var.h):

extern uint32_t tcp_now;  /* for RFC 1323 timestamps */
#define TCP_RETRANSHZ 1000  /* 1ms granularity */

tcp_now tracks milliseconds since boot as a uint32_t. Max value: 4,294,967,295. Divide by 86,400,000 ms/day… yep, ~49.7 days.

Here’s the critical clock update (simplified from calculate_tcp_clock):

struct timeval now;
microuptime(&now);  // ← your ``with_time(&now)`` buddy
current_tcp_now = (uint32_t)now.tv_sec * 1000 + ...;  // The exact line that bites

After ~49.7 days, (uint32_t)now.tv_sec * 1000 wraps around to a tiny number. The monotonicity guard:

if (tmp < current_tcp_now) {  // tmp is still near max
    // Never true after wrap! tcp_now freezes forever
}

Clock stops. Timers relying on it? Dead. TIME_WAIT entries never expire because their expiration check (TSTMP_GEQ(tcp_now, timer)) is now permanently false.

What Actually Happens in the Wild

From Photon’s live experiment (blessing a pair of Macs right at the overflow):

  • Pre-overflow: Blast 15 short connections every 2 seconds → TIME_WAIT stabilizes at ~200. Perfect recycling.
  • At overflow: TIME_WAIT count starts climbing and never stops.
  • Post-overflow: Script stops creating connections. Should drop to zero in 30s. Instead? Keeps growing. Ports exhaust. New TCP handshakes fail.

Existing connections survive. ICMP works. Everything else? “Connection refused” symphony.

This isn’t theoretical – they hit it on their iMessage monitoring fleet. Reboot resets the countdown. Until next month.

Why This Feels Like 1995 All Over Again

Remember Windows 95’s 49.7-day crash? Same 32-bit tick counter family. We’re out here in 2026 still playing unsigned integer roulette with production servers.

Pro tip for the DevOps crowd: If you’re running long-lived macOS boxes (servers, CI runners, monitoring fleets), set up a cron to reboot gracefully every 40 days. Or better yet – use Linux where this particular foot-gun doesn’t exist.

Lessons (Slightly Humorous Edition)

  1. Always handle wraparound – even if “it’ll never happen in prod.”
  2. Monitor uptime – add alerts for “this box is getting suspiciously mature.”
  3. Diverse fleet – don’t put all your eggs in one kernel’s basket.
  4. Chaos test your edge cases – including “what if the clock lies?”
  5. And remember: Every Mac has a hidden expiration date. Like milk, but for TCP.

If you’re running macOS in production for anything socket-heavy, go check your sysctl kern.boottime right now. I’ll wait.

Stay rebooted, friends. May your tcp_now never freeze and your deploys stay boring.

Until next time – keep those kernels humble.

P.S. Apple, if you’re reading this… a 64-bit tcp_now would be a nice patch note. 😏

Reference: https://photon.codes/blog/we-found-a-ticking-time-bomb-in-macos-tcp-networking

// RELATED_ARCHIVES