From c58c9f4cea7fb431a051b45ae6620726e0c5ccd9 Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Sat, 18 Apr 2026 23:26:14 -0400 Subject: [PATCH] Darwin: fix sockaddr_un sun_len causing silent WRITE_START drops The AF_UNIX sun_len field on Darwin is the *total sockaddr struct* length used, not the path length. The current value 'socket_name.size() + 1' is still 1 byte short -- on Darwin the struct layout is: uint8_t sun_len; // 1 byte sa_family_t sun_family; // 1 byte char sun_path[]; // strlen(path) bytes so the portable SUN_LEN macro expands to strlen(path) + 2. Symptom of the off-by-one: update_from_dir's Dispatcher_Client::write_start() would block in select() forever waiting for a WRITE_START ack from the dispatcher. The dispatcher never logged receiving the request -- the kernel silently dropped the message because the sockaddr length header was inconsistent. Reads via the shm + query connections worked because the read protocol does less work on the sockaddr and the mismatch wasn't fatal there. Use the portable SUN_LEN(&local) macro: sizeof(sockaddr_un) - sizeof(sun_path) + strlen(sun_path) On Darwin that expands to strlen(path) + 2, matching what the kernel expects. SUN_LEN is defined in sys/un.h on Darwin, *BSD, and Linux. --- src/template_db/types.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/template_db/types.cc b/src/template_db/types.cc index 7664f4309..1aea8ccb5 100644 --- a/src/template_db/types.cc +++ b/src/template_db/types.cc @@ -120,7 +120,9 @@ void Unix_Socket::open(const std::string& socket_name) else throw File_Error(0, socket_name, "Unix_Socket::3"); #ifdef __APPLE__ - local.sun_len = socket_name.size() + 1; + // SUN_LEN = sizeof(sockaddr_un) - sizeof(sun_path) + strlen(sun_path). + // On Darwin this is strlen(path) + 2 (1 byte sun_len + 1 byte sun_family). + local.sun_len = SUN_LEN(&local); #endif if (max_num_reading_processes > 0)