Selaa lähdekoodia

Merge pull request #4029 from Feoramund/fix-darwin-sigpipe-send

Prevent `SIGPIPE` on Darwin when writing to a closed `core:net` socket
Laytan 1 vuosi sitten
vanhempi
commit
a1c3c38f04
2 muutettua tiedostoa jossa 16 lisäystä ja 4 poistoa
  1. 12 4
      core/net/socket_darwin.odin
  2. 4 0
      core/os/os_darwin.odin

+ 12 - 4
core/net/socket_darwin.odin

@@ -194,8 +194,12 @@ _send_tcp :: proc(skt: TCP_Socket, buf: []byte) -> (bytes_written: int, err: Net
 	for bytes_written < len(buf) {
 		limit := min(int(max(i32)), len(buf) - bytes_written)
 		remaining := buf[bytes_written:][:limit]
-		res, res_err := os.send(os.Socket(skt), remaining, 0)
-		if res_err != nil {
+		res, res_err := os.send(os.Socket(skt), remaining, os.MSG_NOSIGNAL)
+		if res_err == os.EPIPE {
+			// EPIPE arises if the socket has been closed remotely.
+			err = TCP_Send_Error.Connection_Closed
+			return
+		} else if res_err != nil {
 			err = TCP_Send_Error(os.is_platform_error(res_err) or_else -1)
 			return
 		}
@@ -210,8 +214,12 @@ _send_udp :: proc(skt: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written:
 	for bytes_written < len(buf) {
 		limit := min(1<<31, len(buf) - bytes_written)
 		remaining := buf[bytes_written:][:limit]
-		res, res_err := os.sendto(os.Socket(skt), remaining, 0, cast(^os.SOCKADDR)&toaddr, i32(toaddr.len))
-		if res_err != nil {
+		res, res_err := os.sendto(os.Socket(skt), remaining, os.MSG_NOSIGNAL, cast(^os.SOCKADDR)&toaddr, i32(toaddr.len))
+		if res_err == os.EPIPE {
+			// EPIPE arises if the socket has been closed remotely.
+			err = UDP_Send_Error.Not_Socket
+			return
+		} else if res_err != nil {
 			err = UDP_Send_Error(os.is_platform_error(res_err) or_else -1)
 			return
 		}

+ 4 - 0
core/os/os_darwin.odin

@@ -492,6 +492,10 @@ in6_addr :: struct #packed {
 	s6_addr: [16]u8,
 }
 
+// https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/socket.h#L1025-L1027
+// Prevent the raising of SIGPIPE on writing to a closed network socket.
+MSG_NOSIGNAL :: 0x80000
+
 SIOCGIFFLAG :: enum c.int {
 	UP             = 0,  /* Interface is up.  */
 	BROADCAST      = 1,  /* Broadcast address valid.  */