diff options
| author | Laytan Laats <laytanlaats@hotmail.com> | 2024-10-08 21:08:14 +0200 |
|---|---|---|
| committer | Laytan Laats <laytanlaats@hotmail.com> | 2024-10-08 21:08:14 +0200 |
| commit | 5c63617191c92820a497c4d1081c92f1410027fc (patch) | |
| tree | 8796f965b64f652b4a828fdc3760c07d53e43841 /core/net/socket_linux.odin | |
| parent | d8af35f01e71ba1c711cd6d6c5fe0a43116c29f0 (diff) | |
net: fix leaking sockets in listen_tcp if an error occurs
Diffstat (limited to 'core/net/socket_linux.odin')
| -rw-r--r-- | core/net/socket_linux.odin | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index be189f5c1..b7816b0b6 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -167,40 +167,48 @@ _bind :: proc(sock: Any_Socket, endpoint: Endpoint) -> (Network_Error) { } @(private) -_listen_tcp :: proc(endpoint: Endpoint, backlog := 1000) -> (TCP_Socket, Network_Error) { +_listen_tcp :: proc(endpoint: Endpoint, backlog := 1000) -> (socket: TCP_Socket, err: Network_Error) { errno: linux.Errno assert(backlog > 0 && i32(backlog) < max(i32)) + // Figure out the address family and address of the endpoint ep_family := _unwrap_os_family(family_from_endpoint(endpoint)) ep_address := _unwrap_os_addr(endpoint) + // Create TCP socket os_sock: linux.Fd os_sock, errno = linux.socket(ep_family, .STREAM, {.CLOEXEC}, .TCP) if errno != .NONE { - // TODO(flysand): should return invalid file descriptor here casted as TCP_Socket - return {}, Create_Socket_Error(errno) + err = Create_Socket_Error(errno) + return } + socket = cast(TCP_Socket)os_sock + defer if err != nil { close(socket) } + // NOTE(tetra): This is so that if we crash while the socket is open, we can // bypass the cooldown period, and allow the next run of the program to // use the same address immediately. // // TODO(tetra, 2022-02-15): Confirm that this doesn't mean other processes can hijack the address! do_reuse_addr: b32 = true - errno = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &do_reuse_addr) - if errno != .NONE { - return cast(TCP_Socket) os_sock, Listen_Error(errno) + if errno = linux.setsockopt(os_sock, linux.SOL_SOCKET, linux.Socket_Option.REUSEADDR, &do_reuse_addr); errno != .NONE { + err = Listen_Error(errno) + return } + // Bind the socket to endpoint address - errno = linux.bind(os_sock, &ep_address) - if errno != .NONE { - return cast(TCP_Socket) os_sock, Bind_Error(errno) + if errno = linux.bind(os_sock, &ep_address); errno != .NONE { + err = Bind_Error(errno) + return } + // Listen on bound socket - errno = linux.listen(os_sock, cast(i32) backlog) - if errno != .NONE { - return cast(TCP_Socket) os_sock, Listen_Error(errno) + if errno = linux.listen(os_sock, cast(i32) backlog); errno != .NONE { + err = Listen_Error(errno) + return } - return cast(TCP_Socket) os_sock, nil + + return } @(private) |