authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-02 17:38:17-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-05-02 17:38:17-04:00
log1b201f460f99f1ca6a76b1653f4164c52fb10679
tree5bd6f42f9338830975c02fe102bdcf1213944450
parent03a7124543a52f7904090516e572b71b893c7ba2
parent8a8beefa36da8257a328a86340d0d60e1bd569a6

Merge branch 'ninjacato-tomerge-darwin-fix-accept-sockets'

closes #5251

4 files changed, 69 insertions(+), 9 deletions(-)

lib/std/c.zig+1
......@@ -131,6 +131,7 @@ pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint
131131pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
132132pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
133133pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
134pub extern "c" fn accept(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t) c_int;
134135pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int;
135136pub extern "c" fn getsockopt(sockfd: fd_t, level: u32, optname: u32, optval: ?*c_void, optlen: *socklen_t) c_int;
136137pub extern "c" fn setsockopt(sockfd: fd_t, level: u32, optname: u32, optval: ?*const c_void, optlen: socklen_t) c_int;
lib/std/net.zig+1-1
......@@ -1379,7 +1379,7 @@ pub const StreamServer = struct {
13791379 const accept_flags = nonblock | os.SOCK_CLOEXEC;
13801380 var accepted_addr: Address = undefined;
13811381 var adr_len: os.socklen_t = @sizeOf(Address);
1382 if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
1382 if (os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| {
13831383 return Connection{
13841384 .file = fs.File{ .handle = fd },
13851385 .address = accepted_addr,
lib/std/os.zig+58-8
......@@ -2159,9 +2159,20 @@ pub const SocketError = error{
21592159} || UnexpectedError;
21602160
21612161pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!fd_t {
2162 const have_sock_flags = comptime !std.Target.current.isDarwin();
2163 const filtered_sock_type = if (!have_sock_flags)
2164 socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC)
2165 else
2166 socket_type;
21622167 const rc = system.socket(domain, socket_type, protocol);
21632168 switch (errno(rc)) {
2164 0 => return @intCast(fd_t, rc),
2169 0 => {
2170 const fd = @intCast(fd_t, rc);
2171 if (!have_sock_flags and filtered_sock_type != socket_type) {
2172 try setSockFlags(fd, socket_type);
2173 }
2174 return fd;
2175 },
21652176 EACCES => return error.PermissionDenied,
21662177 EAFNOSUPPORT => return error.AddressFamilyNotSupported,
21672178 EINVAL => return error.ProtocolFamilyNotAvailable,
......@@ -2284,7 +2295,7 @@ pub const AcceptError = error{
22842295/// Accept a connection on a socket.
22852296/// If the application has a global event loop enabled, EAGAIN is handled
22862297/// via the event loop. Otherwise EAGAIN results in error.WouldBlock.
2287pub fn accept4(
2298pub fn accept(
22882299 /// This argument is a socket that has been created with `socket`, bound to a local address
22892300 /// with `bind`, and is listening for connections after a `listen`.
22902301 sockfd: fd_t,
......@@ -2300,8 +2311,7 @@ pub fn accept4(
23002311 /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size`
23012312 /// will return a value greater than was supplied to the call.
23022313 addr_size: *socklen_t,
2303 /// If flags is 0, then `accept4` is the same as `accept`. The following values can be bitwise
2304 /// ORed in flags to obtain different behavior:
2314 /// The following values can be bitwise ORed in flags to obtain different behavior:
23052315 /// * `SOCK_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the open file description (see `open`)
23062316 /// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve
23072317 /// the same result.
......@@ -2309,12 +2319,24 @@ pub fn accept4(
23092319 /// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful.
23102320 flags: u32,
23112321) AcceptError!fd_t {
2322 const have_accept4 = comptime !std.Target.current.isDarwin();
2323 assert(0 == (flags & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC))); // Unsupported flag(s)
2324
23122325 while (true) {
2313 const rc = system.accept4(sockfd, addr, addr_size, flags);
2326 const rc = if (have_accept4)
2327 system.accept4(sockfd, addr, addr_size, flags)
2328 else
2329 system.accept(sockfd, addr, addr_size);
2330
23142331 switch (errno(rc)) {
2315 0 => return @intCast(fd_t, rc),
2332 0 => {
2333 const fd = @intCast(fd_t, rc);
2334 if (!have_accept4 and flags != 0) {
2335 try setSockFlags(fd, flags);
2336 }
2337 return fd;
2338 },
23162339 EINTR => continue,
2317
23182340 EAGAIN => if (std.event.Loop.instance) |loop| {
23192341 loop.waitUntilFdReadable(sockfd);
23202342 continue;
......@@ -2333,7 +2355,6 @@ pub fn accept4(
23332355 EOPNOTSUPP => unreachable,
23342356 EPROTO => return error.ProtocolFailure,
23352357 EPERM => return error.BlockedByFirewall,
2336
23372358 else => |err| return unexpectedErrno(err),
23382359 }
23392360 }
......@@ -3245,6 +3266,35 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize {
32453266 }
32463267}
32473268
3269fn setSockFlags(fd: fd_t, flags: u32) !void {
3270 {
3271 var fd_flags = fcntl(fd, F_GETFD, 0) catch |err| switch (err) {
3272 error.FileBusy => unreachable,
3273 error.Locked => unreachable,
3274 else => |e| return e,
3275 };
3276 if ((flags & SOCK_NONBLOCK) != 0) fd_flags |= FD_CLOEXEC;
3277 _ = fcntl(fd, F_SETFD, fd_flags) catch |err| switch (err) {
3278 error.FileBusy => unreachable,
3279 error.Locked => unreachable,
3280 else => |e| return e,
3281 };
3282 }
3283 {
3284 var fl_flags = fcntl(fd, F_GETFL, 0) catch |err| switch (err) {
3285 error.FileBusy => unreachable,
3286 error.Locked => unreachable,
3287 else => |e| return e,
3288 };
3289 if ((flags & SOCK_CLOEXEC) != 0) fl_flags |= O_NONBLOCK;
3290 _ = fcntl(fd, F_SETFL, fl_flags) catch |err| switch (err) {
3291 error.FileBusy => unreachable,
3292 error.Locked => unreachable,
3293 else => |e| return e,
3294 };
3295 }
3296}
3297
32483298pub const FlockError = error{
32493299 WouldBlock,
32503300
lib/std/os/bits/darwin.zig+9
......@@ -764,6 +764,15 @@ pub const SOCK_RDM = 4;
764764pub const SOCK_SEQPACKET = 5;
765765pub const SOCK_MAXADDRLEN = 255;
766766
767/// Not actually supported by Darwin, but Zig supplies a shim.
768/// This numerical value is not ABI-stable. It need only not conflict
769/// with any other "SOCK_" bits.
770pub const SOCK_CLOEXEC = 1 << 15;
771/// Not actually supported by Darwin, but Zig supplies a shim.
772/// This numerical value is not ABI-stable. It need only not conflict
773/// with any other "SOCK_" bits.
774pub const SOCK_NONBLOCK = 1 << 16;
775
767776pub const IPPROTO_ICMP = 1;
768777pub const IPPROTO_ICMPV6 = 58;
769778pub const IPPROTO_TCP = 6;