TCP socket disconnection with EBROKENPIPE during file copy of signed app bundle

We are developing a client server application using TCP bsd sockets. When our client is connected to the server, copying another client .app bundle from a file server on the same machine (using Finder or terminal using cp), occasionally causes the first client to disconnect. The client receives an EBROKENPIPE error when attempting to write to its socket.

In the Console, the following message appears just before the disconnection: necp_socket_find_policy_match: Marking socket in state 258 as defunct

This issue seems to occur only when copying an .app bundle signed with the same TeamIdentifier as the running client. Copying arbitrary files or bundles with a different TeamIdentifier does not trigger the problem.

We are running on macOS 15.5. The issue appears specific to macOS 15 and was not observed on earlier versions.

Any help or pointers would be greatly appreciated!

I’d like to clarify your setup. Specifically, I’d like to get a better understanding of the actors involved. You mentioned:

  • Your “client server application”
  • “a file server on the same machine”
  • Copying “using using Finder or terminal using cp

So, is your client/server app one app? Or two? And is the server running locally as well? Or just the client?

Is the client/server app related to the file server? Or are you using some standard file server protocol, like SMB? And if it’s a standard file server protocol, are you using the built-in client and server implementations? Or something custom?

Also, what version of macOS is this?

And do you see any crash reports generated at the time you see this error?


Oh, and some random notes…

I’m not sure where you got EBROKENPIPE from. The error I’d expect to see when you write to a disconnected socket [1] is EPIPE (32).

necp_socket_find_policy_match: Marking socket in state 258 as defunct

NECP is the subsystem on Apple platforms that manages access to the network. I talk about it in general terms in A Peek Behind the NECP Curtain. I originally suspected that this log message wasn’t a cause, but a symptom. That is, the connection had failed, NECP had noticed that failure, and it’s logging that state change. However, after looking at this specific log message, I’m not so sure.

A defunct socket is one where the underlying resource have been reclaimed. You typically see this on iOS — in TN2277 Networking and Multitasking I explain that cause — but it is possible to get defunct sockets on macOS.

The 258 in that message is the value of the so_state property within the kernel. If you’re curious, you can follow this thread in the Darwin open source. My reading is that it has the SS_NBIO (non-blocking I/O) and SS_ISCONNECTED (connected) flags set. So the socket was connected when NECP defuncted it.

Finally, this scenario reminds me of the issue discussed in Updating Mac Software:

  • It happens seemingly at random.
  • It’s tied to signed code.

However, this is definitely not the standard symptom for such a failure.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Assuming that you’ve disable SIGPIPE, which you typically do via SO_NOSIGPIPE.

Thanks for your help!

So, is your client/server app one app? Or two?

two

And is the server running locally as well? Or just the client?

During the scenario, the server is on another machine.

Is the client/server app related to the file server?

Not at all. Actually we could reproduce the error by copying from a dmg file previously downloaded on the client machine. So the file server is not involved.

Also, what version of macOS is this?

We tested on macOS 15.4 and 15.5.

And do you see any crash reports generated at the time you see this error?

We didn't checked. We will.

I’m not sure where you got EBROKENPIPE from. The error I’d expect to see when you write to a disconnected socket [1] is EPIPE (32).

Right, sorry it's EPIPE(32). Actually we are using openssl + libuv. ssl_write returns error EPIPE(32), we can also get SSL_ERROR_ZERO_RETURN(6) which I think can also be the result of an EPIPE.

Today we got a different log in console during the error (19813 is our tcp port):

  • default 14:01:38.571568+0100 kernel tcp drop outgoing [<IPv4-redacted>:53637<-><IPv4-redacted>:19813] interface: en0 (skipped: 23) so_gencnt: 163620 t_state: CLOSED process: 4D:9220 t_state: CLOSED so_error: 0 reason: NECP

  • default 14:01:38.571602+0100 kernel tcp_connection_summary (tcp_drop:1263)[<IPv4-redacted>:53637<-><IPv4-redacted>:19813] interface: en0 (skipped: 23) so_gencnt: 163620 t_state: CLOSED process: 4D:9220 Duration: 346.780 sec Conn_Time: 0.006 sec bytes in/out: 2886/421 pkts in/out: 9/5 pkt rxmit: 0 ooo pkts: 0 dup bytes in: 0 ACKs delayed: 0 delayed ACKs sent: 0 rtt: 6.000 ms rttvar: 2.125 ms base rtt: 4 ms so_error: 60 svc/tc: 0 flow: 0x9e4027db

  • default 14:01:38.571619+0100 kernel tcp_connection_summary [<IPv4-redacted>:53637<-><IPv4-redacted>:19813] interface: en0 (skipped: 23) so_gencnt: 163620 t_state: CLOSED process: 4D:9220 flowctl: 0us (0x) SYN in/out: 1/1 FIN in/out: 0/0 RST in/out: 0/0 AccECN (client/server): Disabled/Disabled

I see "reason: NECP", but is it the cause or just a notification from NECP?

I'm also puzzled about so_error:60 (ETIMEDOUT) because we are using non blocking sockets with libuv, and we don't use the SO_SNDTIMEO socket option.

Note: most our machines have crowdstrike and rapid7 but we got the error on macs without.

We couldn't isolate the exact conditions for this error to occur. On some mac the symptoms disappeared when we upgraded from macOS 15.4 to 15.5. But some other macs with 15.5 still show the error.

This seems related to the local network privacy permissions: for the error to occur one condition seems to be that the other client.app we copy, which has the same bundle id but a different macho uuid, must not have been authorised yet for local network.

TCP socket disconnection with EBROKENPIPE during file copy of signed app bundle
 
 
Q