| ... | @@ -2657,14 +2657,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t | ... | @@ -2657,14 +2657,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t |
| 2657 | // NOTE: windows translates the SOCK_NONBLOCK/SOCK_CLOEXEC flags into windows-analagous operations | 2657 | // NOTE: windows translates the SOCK_NONBLOCK/SOCK_CLOEXEC flags into windows-analagous operations |
| 2658 | const filtered_sock_type = socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC); | 2658 | const filtered_sock_type = socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC); |
| 2659 | const flags: u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0; | 2659 | const flags: u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0; |
| 2660 | const rc = windows.ws2_32.WSASocketW(@intCast(c_int, domain), @intCast(c_int, filtered_sock_type), @intCast(c_int, protocol), null, 0, flags); | 2660 | const rc = try windows.WSASocketW(@bitCast(i32, domain), @bitCast(i32, filtered_sock_type), @bitCast(i32, protocol), null, 0, flags); |
| 2661 | if (rc == windows.ws2_32.INVALID_SOCKET) switch (windows.ws2_32.WSAGetLastError()) { | | |
| 2662 | .WSAEMFILE => return error.ProcessFdQuotaExceeded, | | |
| 2663 | .WSAENOBUFS => return error.SystemResources, | | |
| 2664 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, | | |
| 2665 | .WSAEPROTONOSUPPORT => return error.ProtocolNotSupported, | | |
| 2666 | else => |err| return windows.unexpectedWSAError(err), | | |
| 2667 | }; | | |
| 2668 | errdefer windows.closesocket(rc) catch unreachable; | 2661 | errdefer windows.closesocket(rc) catch unreachable; |
| 2669 | if ((socket_type & SOCK_NONBLOCK) != 0) { | 2662 | if ((socket_type & SOCK_NONBLOCK) != 0) { |
| 2670 | var mode: c_ulong = 1; // nonblocking | 2663 | var mode: c_ulong = 1; // nonblocking |
| ... | @@ -2741,24 +2734,34 @@ pub const BindError = error{ | ... | @@ -2741,24 +2734,34 @@ pub const BindError = error{ |
| 2741 | } || UnexpectedError; | 2734 | } || UnexpectedError; |
| 2742 | | 2735 | |
| 2743 | /// addr is `*const T` where T is one of the sockaddr | 2736 | /// addr is `*const T` where T is one of the sockaddr |
| 2744 | pub fn bind(sockfd: fd_t, addr: *const sockaddr, len: socklen_t) BindError!void { | 2737 | pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!void { |
| 2745 | const rc = system.bind(sockfd, addr, len); | 2738 | const rc = system.bind(sock, addr, len); |
| 2746 | switch (errno(rc)) { | 2739 | if (builtin.os.tag == .windows) { |
| 2747 | 0 => return, | 2740 | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| 2748 | EACCES => return error.AccessDenied, | 2741 | switch (windows.ws2_32.WSAGetLastError()) { |
| 2749 | EADDRINUSE => return error.AddressInUse, | 2742 | // TODO: handle errors |
| 2750 | EBADF => unreachable, // always a race condition if this error is returned | 2743 | else => |err| return windows.unexpectedWSAError(err), |
| 2751 | EINVAL => unreachable, // invalid parameters | 2744 | } |
| 2752 | ENOTSOCK => unreachable, // invalid `sockfd` | 2745 | } |
| 2753 | EADDRNOTAVAIL => return error.AddressNotAvailable, | 2746 | return; |
| 2754 | EFAULT => unreachable, // invalid `addr` pointer | 2747 | } else { |
| 2755 | ELOOP => return error.SymLinkLoop, | 2748 | switch (errno(rc)) { |
| 2756 | ENAMETOOLONG => return error.NameTooLong, | 2749 | 0 => return, |
| 2757 | ENOENT => return error.FileNotFound, | 2750 | EACCES => return error.AccessDenied, |
| 2758 | ENOMEM => return error.SystemResources, | 2751 | EADDRINUSE => return error.AddressInUse, |
| 2759 | ENOTDIR => return error.NotDir, | 2752 | EBADF => unreachable, // always a race condition if this error is returned |
| 2760 | EROFS => return error.ReadOnlyFileSystem, | 2753 | EINVAL => unreachable, // invalid parameters |
| 2761 | else => |err| return unexpectedErrno(err), | 2754 | ENOTSOCK => unreachable, // invalid `sockfd` |
| | 2755 | EADDRNOTAVAIL => return error.AddressNotAvailable, |
| | 2756 | EFAULT => unreachable, // invalid `addr` pointer |
| | 2757 | ELOOP => return error.SymLinkLoop, |
| | 2758 | ENAMETOOLONG => return error.NameTooLong, |
| | 2759 | ENOENT => return error.FileNotFound, |
| | 2760 | ENOMEM => return error.SystemResources, |
| | 2761 | ENOTDIR => return error.NotDir, |
| | 2762 | EROFS => return error.ReadOnlyFileSystem, |
| | 2763 | else => |err| return unexpectedErrno(err), |
| | 2764 | } |
| 2762 | } | 2765 | } |
| 2763 | } | 2766 | } |
| 2764 | | 2767 | |
| ... | @@ -2777,15 +2780,25 @@ const ListenError = error{ | ... | @@ -2777,15 +2780,25 @@ const ListenError = error{ |
| 2777 | OperationNotSupported, | 2780 | OperationNotSupported, |
| 2778 | } || UnexpectedError; | 2781 | } || UnexpectedError; |
| 2779 | | 2782 | |
| 2780 | pub fn listen(sockfd: fd_t, backlog: u32) ListenError!void { | 2783 | pub fn listen(sock: socket_t, backlog: u31) ListenError!void { |
| 2781 | const rc = system.listen(sockfd, backlog); | 2784 | const rc = system.listen(sock, backlog); |
| 2782 | switch (errno(rc)) { | 2785 | if (builtin.os.tag == .windows) { |
| 2783 | 0 => return, | 2786 | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| 2784 | EADDRINUSE => return error.AddressInUse, | 2787 | switch (windows.ws2_32.WSAGetLastError()) { |
| 2785 | EBADF => unreachable, | 2788 | // TODO: handle errors |
| 2786 | ENOTSOCK => return error.FileDescriptorNotASocket, | 2789 | else => |err| return windows.unexpectedWSAError(err), |
| 2787 | EOPNOTSUPP => return error.OperationNotSupported, | 2790 | } |
| 2788 | else => |err| return unexpectedErrno(err), | 2791 | } |
| | 2792 | return; |
| | 2793 | } else { |
| | 2794 | switch (errno(rc)) { |
| | 2795 | 0 => return, |
| | 2796 | EADDRINUSE => return error.AddressInUse, |
| | 2797 | EBADF => unreachable, |
| | 2798 | ENOTSOCK => return error.FileDescriptorNotASocket, |
| | 2799 | EOPNOTSUPP => return error.OperationNotSupported, |
| | 2800 | else => |err| return unexpectedErrno(err), |
| | 2801 | } |
| 2789 | } | 2802 | } |
| 2790 | } | 2803 | } |
| 2791 | | 2804 | |
| ... | @@ -2822,19 +2835,19 @@ pub const AcceptError = error{ | ... | @@ -2822,19 +2835,19 @@ pub const AcceptError = error{ |
| 2822 | pub fn accept( | 2835 | pub fn accept( |
| 2823 | /// This argument is a socket that has been created with `socket`, bound to a local address | 2836 | /// This argument is a socket that has been created with `socket`, bound to a local address |
| 2824 | /// with `bind`, and is listening for connections after a `listen`. | 2837 | /// with `bind`, and is listening for connections after a `listen`. |
| 2825 | sockfd: fd_t, | 2838 | sock: socket_t, |
| 2826 | /// This argument is a pointer to a sockaddr structure. This structure is filled in with the | 2839 | /// This argument is a pointer to a sockaddr structure. This structure is filled in with the |
| 2827 | /// address of the peer socket, as known to the communications layer. The exact format of the | 2840 | /// address of the peer socket, as known to the communications layer. The exact format of the |
| 2828 | /// address returned addr is determined by the socket's address family (see `socket` and the | 2841 | /// address returned addr is determined by the socket's address family (see `socket` and the |
| 2829 | /// respective protocol man pages). | 2842 | /// respective protocol man pages). |
| 2830 | addr: *sockaddr, | 2843 | addr: ?*sockaddr, |
| 2831 | /// This argument is a value-result argument: the caller must initialize it to contain the | 2844 | /// This argument is a value-result argument: the caller must initialize it to contain the |
| 2832 | /// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size | 2845 | /// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size |
| 2833 | /// of the peer address. | 2846 | /// of the peer address. |
| 2834 | /// | 2847 | /// |
| 2835 | /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size` | 2848 | /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size` |
| 2836 | /// will return a value greater than was supplied to the call. | 2849 | /// will return a value greater than was supplied to the call. |
| 2837 | addr_size: *socklen_t, | 2850 | addr_size: ?*socklen_t, |
| 2838 | /// The following values can be bitwise ORed in flags to obtain different behavior: | 2851 | /// The following values can be bitwise ORed in flags to obtain different behavior: |
| 2839 | /// * `SOCK_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the open file description (see `open`) | 2852 | /// * `SOCK_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the open file description (see `open`) |
| 2840 | /// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve | 2853 | /// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve |
| ... | @@ -2842,46 +2855,58 @@ pub fn accept( | ... | @@ -2842,46 +2855,58 @@ pub fn accept( |
| 2842 | /// * `SOCK_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the | 2855 | /// * `SOCK_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the |
| 2843 | /// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful. | 2856 | /// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful. |
| 2844 | flags: u32, | 2857 | flags: u32, |
| 2845 | ) AcceptError!fd_t { | 2858 | ) AcceptError!socket_t { |
| 2846 | const have_accept4 = comptime !std.Target.current.isDarwin(); | 2859 | const have_accept4 = comptime !(std.Target.current.isDarwin() or builtin.os.tag == .windows); |
| 2847 | assert(0 == (flags & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC))); // Unsupported flag(s) | 2860 | assert(0 == (flags & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC))); // Unsupported flag(s) |
| 2848 | | 2861 | |
| 2849 | while (true) { | 2862 | const accepted_sock = while (true) { |
| 2850 | const rc = if (have_accept4) | 2863 | const rc = if (have_accept4) |
| 2851 | system.accept4(sockfd, addr, addr_size, flags) | 2864 | system.accept4(sock, addr, addr_size, flags) |
| 2852 | else | 2865 | else |
| 2853 | system.accept(sockfd, addr, addr_size); | 2866 | system.accept(sock, addr, addr_size); |
| 2854 | | 2867 | |
| 2855 | switch (errno(rc)) { | 2868 | if (builtin.os.tag == .windows) { |
| 2856 | 0 => { | 2869 | if (rc == windows.ws2_32.INVALID_SOCKET) { |
| 2857 | const fd = @intCast(fd_t, rc); | 2870 | switch (windows.ws2_32.WSAGetLastError()) { |
| 2858 | if (!have_accept4) { | 2871 | // TODO: handle errors |
| 2859 | try setSockFlags(fd, flags); | 2872 | else => |err| return windows.unexpectedWSAError(err), |
| 2860 | } | 2873 | } |
| 2861 | return fd; | | |
| 2862 | }, | | |
| 2863 | EINTR => continue, | | |
| 2864 | EAGAIN => if (std.event.Loop.instance) |loop| { | | |
| 2865 | loop.waitUntilFdReadable(sockfd); | | |
| 2866 | continue; | | |
| 2867 | } else { | 2874 | } else { |
| 2868 | return error.WouldBlock; | 2875 | break rc; |
| 2869 | }, | 2876 | } |
| 2870 | EBADF => unreachable, // always a race condition | 2877 | } else { |
| 2871 | ECONNABORTED => return error.ConnectionAborted, | 2878 | switch (errno(rc)) { |
| 2872 | EFAULT => unreachable, | 2879 | 0 => { |
| 2873 | EINVAL => unreachable, | 2880 | break @intCast(socket_t, rc); |
| 2874 | ENOTSOCK => unreachable, | 2881 | }, |
| 2875 | EMFILE => return error.ProcessFdQuotaExceeded, | 2882 | EINTR => continue, |
| 2876 | ENFILE => return error.SystemFdQuotaExceeded, | 2883 | EAGAIN => if (std.event.Loop.instance) |loop| { |
| 2877 | ENOBUFS => return error.SystemResources, | 2884 | loop.waitUntilFdReadable(sock); |
| 2878 | ENOMEM => return error.SystemResources, | 2885 | continue; |
| 2879 | EOPNOTSUPP => unreachable, | 2886 | } else { |
| 2880 | EPROTO => return error.ProtocolFailure, | 2887 | return error.WouldBlock; |
| 2881 | EPERM => return error.BlockedByFirewall, | 2888 | }, |
| 2882 | else => |err| return unexpectedErrno(err), | 2889 | EBADF => unreachable, // always a race condition |
| | 2890 | ECONNABORTED => return error.ConnectionAborted, |
| | 2891 | EFAULT => unreachable, |
| | 2892 | EINVAL => unreachable, |
| | 2893 | ENOTSOCK => unreachable, |
| | 2894 | EMFILE => return error.ProcessFdQuotaExceeded, |
| | 2895 | ENFILE => return error.SystemFdQuotaExceeded, |
| | 2896 | ENOBUFS => return error.SystemResources, |
| | 2897 | ENOMEM => return error.SystemResources, |
| | 2898 | EOPNOTSUPP => unreachable, |
| | 2899 | EPROTO => return error.ProtocolFailure, |
| | 2900 | EPERM => return error.BlockedByFirewall, |
| | 2901 | else => |err| return unexpectedErrno(err), |
| | 2902 | } |
| 2883 | } | 2903 | } |
| | 2904 | } else unreachable; |
| | 2905 | |
| | 2906 | if (!have_accept4) { |
| | 2907 | try setSockFlags(accepted_sock, flags); |
| 2884 | } | 2908 | } |
| | 2909 | return accepted_sock; |
| 2885 | } | 2910 | } |
| 2886 | | 2911 | |
| 2887 | pub const EpollCreateError = error{ | 2912 | pub const EpollCreateError = error{ |
| ... | @@ -2997,16 +3022,27 @@ pub const GetSockNameError = error{ | ... | @@ -2997,16 +3022,27 @@ pub const GetSockNameError = error{ |
| 2997 | SystemResources, | 3022 | SystemResources, |
| 2998 | } || UnexpectedError; | 3023 | } || UnexpectedError; |
| 2999 | | 3024 | |
| 3000 | pub fn getsockname(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t) GetSockNameError!void { | 3025 | pub fn getsockname(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSockNameError!void { |
| 3001 | switch (errno(system.getsockname(sockfd, addr, addrlen))) { | 3026 | const rc = system.getsockname(sock, addr, addrlen); |
| 3002 | 0 => return, | 3027 | if (builtin.os.tag == .windows) { |
| 3003 | else => |err| return unexpectedErrno(err), | 3028 | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| | 3029 | switch (windows.ws2_32.WSAGetLastError()) { |
| | 3030 | // TODO: handle errors |
| | 3031 | else => |err| return windows.unexpectedWSAError(err), |
| | 3032 | } |
| | 3033 | } |
| | 3034 | return; |
| | 3035 | } else { |
| | 3036 | switch (errno(rc)) { |
| | 3037 | 0 => return, |
| | 3038 | else => |err| return unexpectedErrno(err), |
| 3004 | | 3039 | |
| 3005 | EBADF => unreachable, // always a race condition | 3040 | EBADF => unreachable, // always a race condition |
| 3006 | EFAULT => unreachable, | 3041 | EFAULT => unreachable, |
| 3007 | EINVAL => unreachable, // invalid parameters | 3042 | EINVAL => unreachable, // invalid parameters |
| 3008 | ENOTSOCK => unreachable, | 3043 | ENOTSOCK => unreachable, |
| 3009 | ENOBUFS => return error.SystemResources, | 3044 | ENOBUFS => return error.SystemResources, |
| | 3045 | } |
| 3010 | } | 3046 | } |
| 3011 | } | 3047 | } |
| 3012 | | 3048 | |
| ... | @@ -3052,9 +3088,9 @@ pub const ConnectError = error{ | ... | @@ -3052,9 +3088,9 @@ pub const ConnectError = error{ |
| 3052 | } || UnexpectedError; | 3088 | } || UnexpectedError; |
| 3053 | | 3089 | |
| 3054 | /// Initiate a connection on a socket. | 3090 | /// Initiate a connection on a socket. |
| 3055 | pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void { | 3091 | pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void { |
| 3056 | if (builtin.os.tag == .windows) { | 3092 | if (builtin.os.tag == .windows) { |
| 3057 | const rc = windows.ws2_32.connect(sockfd, sock_addr, len); | 3093 | const rc = windows.ws2_32.connect(sock, sock_addr, len); |
| 3058 | if (rc == 0) return; | 3094 | if (rc == 0) return; |
| 3059 | switch (windows.ws2_32.WSAGetLastError()) { | 3095 | switch (windows.ws2_32.WSAGetLastError()) { |
| 3060 | .WSAEADDRINUSE => return error.AddressInUse, | 3096 | .WSAEADDRINUSE => return error.AddressInUse, |
| ... | @@ -3077,7 +3113,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con | ... | @@ -3077,7 +3113,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con |
| 3077 | } | 3113 | } |
| 3078 | | 3114 | |
| 3079 | while (true) { | 3115 | while (true) { |
| 3080 | switch (errno(system.connect(sockfd, sock_addr, len))) { | 3116 | switch (errno(system.connect(sock, sock_addr, len))) { |
| 3081 | 0 => return, | 3117 | 0 => return, |
| 3082 | EACCES => return error.PermissionDenied, | 3118 | EACCES => return error.PermissionDenied, |
| 3083 | EPERM => return error.PermissionDenied, | 3119 | EPERM => return error.PermissionDenied, |
| ... | @@ -3086,8 +3122,8 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con | ... | @@ -3086,8 +3122,8 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con |
| 3086 | EAFNOSUPPORT => return error.AddressFamilyNotSupported, | 3122 | EAFNOSUPPORT => return error.AddressFamilyNotSupported, |
| 3087 | EAGAIN, EINPROGRESS => { | 3123 | EAGAIN, EINPROGRESS => { |
| 3088 | const loop = std.event.Loop.instance orelse return error.WouldBlock; | 3124 | const loop = std.event.Loop.instance orelse return error.WouldBlock; |
| 3089 | loop.waitUntilFdWritable(sockfd); | 3125 | loop.waitUntilFdWritable(sock); |
| 3090 | return getsockoptError(sockfd); | 3126 | return getsockoptError(sock); |
| 3091 | }, | 3127 | }, |
| 3092 | EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. | 3128 | EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. |
| 3093 | EBADF => unreachable, // sockfd is not a valid open file descriptor. | 3129 | EBADF => unreachable, // sockfd is not a valid open file descriptor. |
| ... | @@ -3928,32 +3964,46 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { | ... | @@ -3928,32 +3964,46 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { |
| 3928 | } | 3964 | } |
| 3929 | } | 3965 | } |
| 3930 | | 3966 | |
| 3931 | fn setSockFlags(fd: fd_t, flags: u32) !void { | 3967 | fn setSockFlags(sock: socket_t, flags: u32) !void { |
| 3932 | if ((flags & SOCK_CLOEXEC) != 0) { | 3968 | if ((flags & SOCK_CLOEXEC) != 0) { |
| 3933 | var fd_flags = fcntl(fd, F_GETFD, 0) catch |err| switch (err) { | 3969 | if (builtin.os.tag == .windows) { |
| 3934 | error.FileBusy => unreachable, | 3970 | // TODO: Find out if this is supported for sockets |
| 3935 | error.Locked => unreachable, | 3971 | } else { |
| 3936 | else => |e| return e, | 3972 | var fd_flags = fcntl(sock, F_GETFD, 0) catch |err| switch (err) { |
| 3937 | }; | 3973 | error.FileBusy => unreachable, |
| 3938 | fd_flags |= FD_CLOEXEC; | 3974 | error.Locked => unreachable, |
| 3939 | _ = fcntl(fd, F_SETFD, fd_flags) catch |err| switch (err) { | 3975 | else => |e| return e, |
| 3940 | error.FileBusy => unreachable, | 3976 | }; |
| 3941 | error.Locked => unreachable, | 3977 | fd_flags |= FD_CLOEXEC; |
| 3942 | else => |e| return e, | 3978 | _ = fcntl(sock, F_SETFD, fd_flags) catch |err| switch (err) { |
| 3943 | }; | 3979 | error.FileBusy => unreachable, |
| | 3980 | error.Locked => unreachable, |
| | 3981 | else => |e| return e, |
| | 3982 | }; |
| | 3983 | } |
| 3944 | } | 3984 | } |
| 3945 | if ((flags & SOCK_NONBLOCK) != 0) { | 3985 | if ((flags & SOCK_NONBLOCK) != 0) { |
| 3946 | var fl_flags = fcntl(fd, F_GETFL, 0) catch |err| switch (err) { | 3986 | if (builtin.os.tag == .windows) { |
| 3947 | error.FileBusy => unreachable, | 3987 | var mode: c_ulong = 1; |
| 3948 | error.Locked => unreachable, | 3988 | if (windows.ws2_32.ioctlsocket(sock, windows.ws2_32.FIONBIO, &mode) == windows.ws2_32.SOCKET_ERROR) { |
| 3949 | else => |e| return e, | 3989 | switch (windows.ws2_32.WSAGetLastError()) { |
| 3950 | }; | 3990 | // TODO: handle errors |
| 3951 | fl_flags |= O_NONBLOCK; | 3991 | else => |err| return windows.unexpectedWSAError(err), |
| 3952 | _ = fcntl(fd, F_SETFL, fl_flags) catch |err| switch (err) { | 3992 | } |
| 3953 | error.FileBusy => unreachable, | 3993 | } |
| 3954 | error.Locked => unreachable, | 3994 | } else { |
| 3955 | else => |e| return e, | 3995 | var fl_flags = fcntl(sock, F_GETFL, 0) catch |err| switch (err) { |
| 3956 | }; | 3996 | error.FileBusy => unreachable, |
| | 3997 | error.Locked => unreachable, |
| | 3998 | else => |e| return e, |
| | 3999 | }; |
| | 4000 | fl_flags |= O_NONBLOCK; |
| | 4001 | _ = fcntl(sock, F_SETFL, fl_flags) catch |err| switch (err) { |
| | 4002 | error.FileBusy => unreachable, |
| | 4003 | error.Locked => unreachable, |
| | 4004 | else => |e| return e, |
| | 4005 | }; |
| | 4006 | } |
| 3957 | } | 4007 | } |
| 3958 | } | 4008 | } |
| 3959 | | 4009 | |