| author | |
| committer | |
| log | e85a10e9f5f6b17736babd321da8dceb72ea17af |
| tree | 70b94f7e1e5f761ad6fe95138ef9832cd0c32baf |
| parent | cbda0fa78c37dd84821061309469c85a2281174c |
11 files changed, 231 insertions(+), 50 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -432,6 +432,7 @@ set(ZIG_STD_FILES |
| 432 | 432 | "dwarf.zig" |
| 433 | 433 | "elf.zig" |
| 434 | 434 | "empty.zig" |
| 435 | "event.zig" | |
| 435 | 436 | "fmt/errol/enum3.zig" |
| 436 | 437 | "fmt/errol/index.zig" |
| 437 | 438 | "fmt/errol/lookup.zig" |
src/codegen.cpp+3| ... | ... | @@ -408,6 +408,9 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e |
| 408 | 408 | if (!g->have_err_ret_tracing) { |
| 409 | 409 | return UINT32_MAX; |
| 410 | 410 | } |
| 411 | if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) { | |
| 412 | return 0; | |
| 413 | } | |
| 411 | 414 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 412 | 415 | if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) { |
| 413 | 416 | return UINT32_MAX; |
src/ir.cpp+22-11| ... | ... | @@ -2755,9 +2755,10 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) { |
| 2755 | 2755 | |
| 2756 | 2756 | static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) { |
| 2757 | 2757 | Scope *scope = inner_scope; |
| 2758 | bool is_noreturn = false; | |
| 2758 | 2759 | while (scope != outer_scope) { |
| 2759 | 2760 | if (!scope) |
| 2760 | return false; | |
| 2761 | return is_noreturn; | |
| 2761 | 2762 | |
| 2762 | 2763 | if (scope->id == ScopeIdDefer) { |
| 2763 | 2764 | AstNode *defer_node = scope->source_node; |
| ... | ... | @@ -2770,14 +2771,18 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o |
| 2770 | 2771 | Scope *defer_expr_scope = defer_node->data.defer.expr_scope; |
| 2771 | 2772 | IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); |
| 2772 | 2773 | if (defer_expr_value != irb->codegen->invalid_instruction) { |
| 2773 | ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value)); | |
| 2774 | if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == TypeTableEntryIdUnreachable) { | |
| 2775 | is_noreturn = true; | |
| 2776 | } else { | |
| 2777 | ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value)); | |
| 2778 | } | |
| 2774 | 2779 | } |
| 2775 | 2780 | } |
| 2776 | 2781 | |
| 2777 | 2782 | } |
| 2778 | 2783 | scope = scope->parent; |
| 2779 | 2784 | } |
| 2780 | return true; | |
| 2785 | return is_noreturn; | |
| 2781 | 2786 | } |
| 2782 | 2787 | |
| 2783 | 2788 | static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { |
| ... | ... | @@ -2936,12 +2941,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2936 | 2941 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); |
| 2937 | 2942 | |
| 2938 | 2943 | ir_set_cursor_at_end_and_append_block(irb, return_block); |
| 2939 | ir_gen_defers_for_block(irb, scope, outer_scope, true); | |
| 2940 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); | |
| 2941 | if (irb->codegen->have_err_ret_tracing && !should_inline) { | |
| 2942 | ir_build_save_err_ret_addr(irb, scope, node); | |
| 2944 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) { | |
| 2945 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr); | |
| 2946 | if (irb->codegen->have_err_ret_tracing && !should_inline) { | |
| 2947 | ir_build_save_err_ret_addr(irb, scope, node); | |
| 2948 | } | |
| 2949 | ir_gen_async_return(irb, scope, node, err_val, false); | |
| 2943 | 2950 | } |
| 2944 | ir_gen_async_return(irb, scope, node, err_val, false); | |
| 2945 | 2951 | |
| 2946 | 2952 | ir_set_cursor_at_end_and_append_block(irb, continue_block); |
| 2947 | 2953 | IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false); |
| ... | ... | @@ -5695,7 +5701,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast |
| 5695 | 5701 | |
| 5696 | 5702 | IrBasicBlock *dest_block = loop_scope->continue_block; |
| 5697 | 5703 | ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false); |
| 5698 | return ir_build_br(irb, continue_scope, node, dest_block, is_comptime); | |
| 5704 | return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); | |
| 5699 | 5705 | } |
| 5700 | 5706 | |
| 5701 | 5707 | static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) { |
| ... | ... | @@ -6178,7 +6184,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast |
| 6178 | 6184 | |
| 6179 | 6185 | ir_set_cursor_at_end_and_append_block(irb, cleanup_block); |
| 6180 | 6186 | ir_gen_defers_for_block(irb, parent_scope, outer_scope, true); |
| 6181 | ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false); | |
| 6187 | ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false)); | |
| 6182 | 6188 | |
| 6183 | 6189 | ir_set_cursor_at_end_and_append_block(irb, resume_block); |
| 6184 | 6190 | IrInstruction *yes_suspend_result = ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr); |
| ... | ... | @@ -6254,7 +6260,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod |
| 6254 | 6260 | |
| 6255 | 6261 | ir_set_cursor_at_end_and_append_block(irb, cleanup_block); |
| 6256 | 6262 | ir_gen_defers_for_block(irb, parent_scope, outer_scope, true); |
| 6257 | ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false); | |
| 6263 | ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false)); | |
| 6258 | 6264 | |
| 6259 | 6265 | ir_set_cursor_at_end_and_append_block(irb, resume_block); |
| 6260 | 6266 | return ir_build_const_void(irb, parent_scope, node); |
| ... | ... | @@ -16746,6 +16752,11 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc |
| 16746 | 16752 | return ira->codegen->builtin_types.entry_invalid; |
| 16747 | 16753 | |
| 16748 | 16754 | if (fn_type_id.cc == CallingConventionAsync) { |
| 16755 | if (instruction->async_allocator_type_value == nullptr) { | |
| 16756 | ir_add_error(ira, &instruction->base, | |
| 16757 | buf_sprintf("async fn proto missing allocator type")); | |
| 16758 | return ira->codegen->builtin_types.entry_invalid; | |
| 16759 | } | |
| 16749 | 16760 | IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->other; |
| 16750 | 16761 | fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value); |
| 16751 | 16762 | if (type_is_invalid(fn_type_id.async_allocator_type)) |
std/c/darwin.zig+8| ... | ... | @@ -55,3 +55,11 @@ pub const dirent = extern struct { |
| 55 | 55 | d_type: u8, |
| 56 | 56 | d_name: u8, // field address is address of first byte of name |
| 57 | 57 | }; |
| 58 | ||
| 59 | pub const sockaddr = extern struct { | |
| 60 | sa_len: u8, | |
| 61 | sa_family: sa_family_t, | |
| 62 | sa_data: [14]u8, | |
| 63 | }; | |
| 64 | ||
| 65 | pub const sa_family_t = u8; |
std/event.zig+36-9| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("index.zig"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const assert = std.debug.assert; |
| 3 | 4 | const event = this; |
| 4 | 5 | const mem = std.mem; |
| ... | ... | @@ -38,7 +39,7 @@ pub const TcpServer = struct { |
| 38 | 39 | { |
| 39 | 40 | self.handleRequestFn = handleRequestFn; |
| 40 | 41 | |
| 41 | try std.os.posixBind(self.sockfd, &address.sockaddr); | |
| 42 | try std.os.posixBind(self.sockfd, &address.os_addr); | |
| 42 | 43 | try std.os.posixListen(self.sockfd, posix.SOMAXCONN); |
| 43 | 44 | self.listen_address = std.net.Address.initPosix(try std.os.posixGetSockName(self.sockfd)); |
| 44 | 45 | |
| ... | ... | @@ -59,7 +60,7 @@ pub const TcpServer = struct { |
| 59 | 60 | pub async fn handler(self: &TcpServer) void { |
| 60 | 61 | while (true) { |
| 61 | 62 | var accepted_addr: std.net.Address = undefined; |
| 62 | if (std.os.posixAccept(self.sockfd, &accepted_addr.sockaddr, | |
| 63 | if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr, | |
| 63 | 64 | posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| |
| 64 | 65 | { |
| 65 | 66 | var socket = std.os.File.openHandle(accepted_fd); |
| ... | ... | @@ -118,7 +119,7 @@ pub const Loop = struct { |
| 118 | 119 | |
| 119 | 120 | pub fn addFd(self: &Loop, fd: i32, prom: promise) !void { |
| 120 | 121 | var ev = std.os.linux.epoll_event { |
| 121 | .events = std.os.linux.EPOLLIN|std.os.linux.EPOLLET, | |
| 122 | .events = std.os.linux.EPOLLIN|std.os.linux.EPOLLOUT|std.os.linux.EPOLLET, | |
| 122 | 123 | .data = std.os.linux.epoll_data { |
| 123 | 124 | .ptr = @ptrToInt(prom), |
| 124 | 125 | }, |
| ... | ... | @@ -155,7 +156,24 @@ pub const Loop = struct { |
| 155 | 156 | } |
| 156 | 157 | }; |
| 157 | 158 | |
| 159 | pub async fn connect(loop: &Loop, _address: &const std.net.Address) !std.os.File { | |
| 160 | var address = *_address; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 161 | ||
| 162 | const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, posix.PROTO_tcp); | |
| 163 | errdefer std.os.close(sockfd); | |
| 164 | ||
| 165 | try std.os.posixConnectAsync(sockfd, &address.os_addr); | |
| 166 | try await try async loop.waitFd(sockfd); | |
| 167 | try std.os.posixGetSockOptConnectError(sockfd); | |
| 168 | ||
| 169 | return std.os.File.openHandle(sockfd); | |
| 170 | } | |
| 171 | ||
| 158 | 172 | test "listen on a port, send bytes, receive bytes" { |
| 173 | if (builtin.os != builtin.Os.linux) { | |
| 174 | // TODO build abstractions for other operating systems | |
| 175 | return; | |
| 176 | } | |
| 159 | 177 | const MyServer = struct { |
| 160 | 178 | tcp_server: TcpServer, |
| 161 | 179 | |
| ... | ... | @@ -198,11 +216,20 @@ test "listen on a port, send bytes, receive bytes" { |
| 198 | 216 | defer server.tcp_server.deinit(); |
| 199 | 217 | try server.tcp_server.listen(addr, MyServer.handler); |
| 200 | 218 | |
| 201 | var stderr_file = try std.io.getStdErr(); | |
| 202 | var stderr_stream = &std.io.FileOutStream.init(&stderr_file).stream; | |
| 203 | try stderr_stream.print("\nlistening at "); | |
| 204 | try server.tcp_server.listen_address.format(stderr_stream); | |
| 205 | try stderr_stream.print("\n"); | |
| 206 | ||
| 219 | const p = try async<std.debug.global_allocator> doAsyncTest(&loop, server.tcp_server.listen_address); | |
| 220 | defer cancel p; | |
| 207 | 221 | loop.run(); |
| 208 | 222 | } |
| 223 | ||
| 224 | async fn doAsyncTest(loop: &Loop, address: &const std.net.Address) void { | |
| 225 | errdefer @panic("test failure"); | |
| 226 | ||
| 227 | var socket_file = try await try async event.connect(loop, address); | |
| 228 | defer socket_file.close(); | |
| 229 | ||
| 230 | var buf: [512]u8 = undefined; | |
| 231 | const amt_read = try socket_file.read(buf[0..]); | |
| 232 | const msg = buf[0..amt_read]; | |
| 233 | assert(mem.eql(u8, msg, "hello from server\n")); | |
| 234 | loop.stop(); | |
| 235 | } |
std/index.zig+1-1| ... | ... | @@ -50,7 +50,7 @@ test "std" { |
| 50 | 50 | _ = @import("dwarf.zig"); |
| 51 | 51 | _ = @import("elf.zig"); |
| 52 | 52 | _ = @import("empty.zig"); |
| 53 | //TODO_ = @import("event.zig"); | |
| 53 | _ = @import("event.zig"); | |
| 54 | 54 | _ = @import("fmt/index.zig"); |
| 55 | 55 | _ = @import("hash/index.zig"); |
| 56 | 56 | _ = @import("io.zig"); |
std/net.zig+19-8| ... | ... | @@ -1,15 +1,26 @@ |
| 1 | 1 | const std = @import("index.zig"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const assert = std.debug.assert; |
| 3 | 4 | const net = this; |
| 4 | 5 | const posix = std.os.posix; |
| 5 | 6 | const mem = std.mem; |
| 6 | 7 | |
| 8 | pub const TmpWinAddr = struct { | |
| 9 | family: u8, | |
| 10 | data: [14]u8, | |
| 11 | }; | |
| 12 | ||
| 13 | pub const OsAddress = switch (builtin.os) { | |
| 14 | builtin.Os.windows => TmpWinAddr, | |
| 15 | else => posix.sockaddr, | |
| 16 | }; | |
| 17 | ||
| 7 | 18 | pub const Address = struct { |
| 8 | sockaddr: posix.sockaddr, | |
| 19 | os_addr: OsAddress, | |
| 9 | 20 | |
| 10 | 21 | pub fn initIp4(ip4: u32, port: u16) Address { |
| 11 | 22 | return Address { |
| 12 | .sockaddr = posix.sockaddr { | |
| 23 | .os_addr = posix.sockaddr { | |
| 13 | 24 | .in = posix.sockaddr_in { |
| 14 | 25 | .family = posix.AF_INET, |
| 15 | 26 | .port = std.mem.endianSwapIfLe(u16, port), |
| ... | ... | @@ -23,7 +34,7 @@ pub const Address = struct { |
| 23 | 34 | pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address { |
| 24 | 35 | return Address { |
| 25 | 36 | .family = posix.AF_INET6, |
| 26 | .sockaddr = posix.sockaddr { | |
| 37 | .os_addr = posix.sockaddr { | |
| 27 | 38 | .in6 = posix.sockaddr_in6 { |
| 28 | 39 | .family = posix.AF_INET6, |
| 29 | 40 | .port = std.mem.endianSwapIfLe(u16, port), |
| ... | ... | @@ -37,19 +48,19 @@ pub const Address = struct { |
| 37 | 48 | |
| 38 | 49 | pub fn initPosix(addr: &const posix.sockaddr) Address { |
| 39 | 50 | return Address { |
| 40 | .sockaddr = *addr, | |
| 51 | .os_addr = *addr, | |
| 41 | 52 | }; |
| 42 | 53 | } |
| 43 | 54 | |
| 44 | 55 | pub fn format(self: &const Address, out_stream: var) !void { |
| 45 | switch (self.sockaddr.in.family) { | |
| 56 | switch (self.os_addr.in.family) { | |
| 46 | 57 | posix.AF_INET => { |
| 47 | const native_endian_port = std.mem.endianSwapIfLe(u16, self.sockaddr.in.port); | |
| 48 | const bytes = ([]const u8)((&self.sockaddr.in.addr)[0..1]); | |
| 58 | const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port); | |
| 59 | const bytes = ([]const u8)((&self.os_addr.in.addr)[0..1]); | |
| 49 | 60 | try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port); |
| 50 | 61 | }, |
| 51 | 62 | posix.AF_INET6 => { |
| 52 | const native_endian_port = std.mem.endianSwapIfLe(u16, self.sockaddr.in6.port); | |
| 63 | const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port); | |
| 53 | 64 | try out_stream.print("[TODO render ip6 address]:{}", native_endian_port); |
| 54 | 65 | }, |
| 55 | 66 | else => try out_stream.write("(unrecognized address family)"), |
std/os/darwin.zig+3| ... | ... | @@ -301,6 +301,9 @@ pub const timespec = c.timespec; |
| 301 | 301 | pub const Stat = c.Stat; |
| 302 | 302 | pub const dirent = c.dirent; |
| 303 | 303 | |
| 304 | pub const sa_family_t = c.sa_family_t; | |
| 305 | pub const sockaddr = c.sockaddr; | |
| 306 | ||
| 304 | 307 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 305 | 308 | pub const Sigaction = struct { |
| 306 | 309 | handler: extern fn(i32)void, |
std/os/index.zig+132-1| ... | ... | @@ -2217,7 +2217,7 @@ pub fn linuxEpollCtl(epfd: i32, op: u32, fd: i32, event: &linux.epoll_event) Lin |
| 2217 | 2217 | |
| 2218 | 2218 | pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usize { |
| 2219 | 2219 | while (true) { |
| 2220 | const rc = posix.epoll_wait(epfd, &events[0], u32(events.len), timeout); | |
| 2220 | const rc = posix.epoll_wait(epfd, events.ptr, u32(events.len), timeout); | |
| 2221 | 2221 | const err = posix.getErrno(rc); |
| 2222 | 2222 | switch (err) { |
| 2223 | 2223 | 0 => return rc, |
| ... | ... | @@ -2253,3 +2253,134 @@ pub fn posixGetSockName(sockfd: i32) PosixGetSockNameError!posix.sockaddr { |
| 2253 | 2253 | posix.ENOBUFS => return PosixGetSockNameError.SystemResources, |
| 2254 | 2254 | } |
| 2255 | 2255 | } |
| 2256 | ||
| 2257 | pub const PosixConnectError = error { | |
| 2258 | /// For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket | |
| 2259 | /// file, or search permission is denied for one of the directories in the path prefix. | |
| 2260 | /// or | |
| 2261 | /// The user tried to connect to a broadcast address without having the socket broadcast flag enabled or | |
| 2262 | /// the connection request failed because of a local firewall rule. | |
| 2263 | PermissionDenied, | |
| 2264 | ||
| 2265 | /// Local address is already in use. | |
| 2266 | AddressInUse, | |
| 2267 | ||
| 2268 | /// (Internet domain sockets) The socket referred to by sockfd had not previously been bound to an | |
| 2269 | /// address and, upon attempting to bind it to an ephemeral port, it was determined that all port numbers | |
| 2270 | /// in the ephemeral port range are currently in use. See the discussion of | |
| 2271 | /// /proc/sys/net/ipv4/ip_local_port_range in ip(7). | |
| 2272 | AddressNotAvailable, | |
| 2273 | ||
| 2274 | /// The passed address didn't have the correct address family in its sa_family field. | |
| 2275 | AddressFamilyNotSupported, | |
| 2276 | ||
| 2277 | /// Insufficient entries in the routing cache. | |
| 2278 | SystemResources, | |
| 2279 | ||
| 2280 | /// A connect() on a stream socket found no one listening on the remote address. | |
| 2281 | ConnectionRefused, | |
| 2282 | ||
| 2283 | /// Network is unreachable. | |
| 2284 | NetworkUnreachable, | |
| 2285 | ||
| 2286 | /// Timeout while attempting connection. The server may be too busy to accept new connections. Note | |
| 2287 | /// that for IP sockets the timeout may be very long when syncookies are enabled on the server. | |
| 2288 | ConnectionTimedOut, | |
| 2289 | ||
| 2290 | Unexpected, | |
| 2291 | }; | |
| 2292 | ||
| 2293 | pub fn posixConnect(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConnectError!void { | |
| 2294 | while (true) { | |
| 2295 | const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr)); | |
| 2296 | const err = posix.getErrno(rc); | |
| 2297 | switch (err) { | |
| 2298 | 0 => return, | |
| 2299 | else => return unexpectedErrorPosix(err), | |
| 2300 | ||
| 2301 | posix.EACCES => return PosixConnectError.PermissionDenied, | |
| 2302 | posix.EPERM => return PosixConnectError.PermissionDenied, | |
| 2303 | posix.EADDRINUSE => return PosixConnectError.AddressInUse, | |
| 2304 | posix.EADDRNOTAVAIL => return PosixConnectError.AddressNotAvailable, | |
| 2305 | posix.EAFNOSUPPORT => return PosixConnectError.AddressFamilyNotSupported, | |
| 2306 | posix.EAGAIN => return PosixConnectError.SystemResources, | |
| 2307 | posix.EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. | |
| 2308 | posix.EBADF => unreachable, // sockfd is not a valid open file descriptor. | |
| 2309 | posix.ECONNREFUSED => return PosixConnectError.ConnectionRefused, | |
| 2310 | posix.EFAULT => unreachable, // The socket structure address is outside the user's address space. | |
| 2311 | posix.EINPROGRESS => unreachable, // The socket is nonblocking and the connection cannot be completed immediately. | |
| 2312 | posix.EINTR => continue, | |
| 2313 | posix.EISCONN => unreachable, // The socket is already connected. | |
| 2314 | posix.ENETUNREACH => return PosixConnectError.NetworkUnreachable, | |
| 2315 | posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. | |
| 2316 | posix.EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol. | |
| 2317 | posix.ETIMEDOUT => return PosixConnectError.ConnectionTimedOut, | |
| 2318 | } | |
| 2319 | } | |
| 2320 | } | |
| 2321 | ||
| 2322 | /// Same as posixConnect except it is for blocking socket file descriptors. | |
| 2323 | /// It expects to receive EINPROGRESS. | |
| 2324 | pub fn posixConnectAsync(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConnectError!void { | |
| 2325 | while (true) { | |
| 2326 | const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr)); | |
| 2327 | const err = posix.getErrno(rc); | |
| 2328 | switch (err) { | |
| 2329 | 0, posix.EINPROGRESS => return, | |
| 2330 | else => return unexpectedErrorPosix(err), | |
| 2331 | ||
| 2332 | posix.EACCES => return PosixConnectError.PermissionDenied, | |
| 2333 | posix.EPERM => return PosixConnectError.PermissionDenied, | |
| 2334 | posix.EADDRINUSE => return PosixConnectError.AddressInUse, | |
| 2335 | posix.EADDRNOTAVAIL => return PosixConnectError.AddressNotAvailable, | |
| 2336 | posix.EAFNOSUPPORT => return PosixConnectError.AddressFamilyNotSupported, | |
| 2337 | posix.EAGAIN => return PosixConnectError.SystemResources, | |
| 2338 | posix.EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. | |
| 2339 | posix.EBADF => unreachable, // sockfd is not a valid open file descriptor. | |
| 2340 | posix.ECONNREFUSED => return PosixConnectError.ConnectionRefused, | |
| 2341 | posix.EFAULT => unreachable, // The socket structure address is outside the user's address space. | |
| 2342 | posix.EINTR => continue, | |
| 2343 | posix.EISCONN => unreachable, // The socket is already connected. | |
| 2344 | posix.ENETUNREACH => return PosixConnectError.NetworkUnreachable, | |
| 2345 | posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. | |
| 2346 | posix.EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol. | |
| 2347 | posix.ETIMEDOUT => return PosixConnectError.ConnectionTimedOut, | |
| 2348 | } | |
| 2349 | } | |
| 2350 | } | |
| 2351 | ||
| 2352 | pub fn posixGetSockOptConnectError(sockfd: i32) PosixConnectError!void { | |
| 2353 | var err_code: i32 = undefined; | |
| 2354 | var size: u32 = @sizeOf(i32); | |
| 2355 | const rc = posix.getsockopt(sockfd, posix.SOL_SOCKET, posix.SO_ERROR, @ptrCast(&u8, &err_code), &size); | |
| 2356 | assert(size == 4); | |
| 2357 | const err = posix.getErrno(rc); | |
| 2358 | switch (err) { | |
| 2359 | 0 => switch (err_code) { | |
| 2360 | 0 => return, | |
| 2361 | else => return unexpectedErrorPosix(err), | |
| 2362 | ||
| 2363 | posix.EACCES => return PosixConnectError.PermissionDenied, | |
| 2364 | posix.EPERM => return PosixConnectError.PermissionDenied, | |
| 2365 | posix.EADDRINUSE => return PosixConnectError.AddressInUse, | |
| 2366 | posix.EADDRNOTAVAIL => return PosixConnectError.AddressNotAvailable, | |
| 2367 | posix.EAFNOSUPPORT => return PosixConnectError.AddressFamilyNotSupported, | |
| 2368 | posix.EAGAIN => return PosixConnectError.SystemResources, | |
| 2369 | posix.EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. | |
| 2370 | posix.EBADF => unreachable, // sockfd is not a valid open file descriptor. | |
| 2371 | posix.ECONNREFUSED => return PosixConnectError.ConnectionRefused, | |
| 2372 | posix.EFAULT => unreachable, // The socket structure address is outside the user's address space. | |
| 2373 | posix.EISCONN => unreachable, // The socket is already connected. | |
| 2374 | posix.ENETUNREACH => return PosixConnectError.NetworkUnreachable, | |
| 2375 | posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. | |
| 2376 | posix.EPROTOTYPE => unreachable, // The socket type does not support the requested communications protocol. | |
| 2377 | posix.ETIMEDOUT => return PosixConnectError.ConnectionTimedOut, | |
| 2378 | }, | |
| 2379 | else => return unexpectedErrorPosix(err), | |
| 2380 | posix.EBADF => unreachable, // The argument sockfd is not a valid file descriptor. | |
| 2381 | posix.EFAULT => unreachable, // The address pointed to by optval or optlen is not in a valid part of the process address space. | |
| 2382 | posix.EINVAL => unreachable, | |
| 2383 | posix.ENOPROTOOPT => unreachable, // The option is unknown at the level indicated. | |
| 2384 | posix.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. | |
| 2385 | } | |
| 2386 | } |
std/os/linux/index.zig+6-6| ... | ... | @@ -775,12 +775,12 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { |
| 775 | 775 | return syscall3(SYS_socket, domain, socket_type, protocol); |
| 776 | 776 | } |
| 777 | 777 | |
| 778 | pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) usize { | |
| 779 | return syscall5(SYS_setsockopt, usize(fd), usize(level), usize(optname), usize(optval), @ptrToInt(optlen)); | |
| 778 | pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: &const u8, optlen: socklen_t) usize { | |
| 779 | return syscall5(SYS_setsockopt, usize(fd), level, optname, usize(optval), @ptrToInt(optlen)); | |
| 780 | 780 | } |
| 781 | 781 | |
| 782 | pub fn getsockopt(fd: i32, level: i32, optname: i32, noalias optval: &u8, noalias optlen: &socklen_t) usize { | |
| 783 | return syscall5(SYS_getsockopt, usize(fd), usize(level), usize(optname), @ptrToInt(optval), @ptrToInt(optlen)); | |
| 782 | pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: &u8, noalias optlen: &socklen_t) usize { | |
| 783 | return syscall5(SYS_getsockopt, usize(fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); | |
| 784 | 784 | } |
| 785 | 785 | |
| 786 | 786 | pub fn sendmsg(fd: i32, msg: &const msghdr, flags: u32) usize { |
| ... | ... | @@ -833,14 +833,14 @@ pub fn fstat(fd: i32, stat_buf: &Stat) usize { |
| 833 | 833 | return syscall2(SYS_fstat, usize(fd), @ptrToInt(stat_buf)); |
| 834 | 834 | } |
| 835 | 835 | |
| 836 | pub const epoll_data = extern union { | |
| 836 | pub const epoll_data = packed union { | |
| 837 | 837 | ptr: usize, |
| 838 | 838 | fd: i32, |
| 839 | 839 | @"u32": u32, |
| 840 | 840 | @"u64": u64, |
| 841 | 841 | }; |
| 842 | 842 | |
| 843 | pub const epoll_event = extern struct { | |
| 843 | pub const epoll_event = packed struct { | |
| 844 | 844 | events: u32, |
| 845 | 845 | data: epoll_data, |
| 846 | 846 | }; |
test/cases/coroutines.zig-14| ... | ... | @@ -224,17 +224,3 @@ async fn printTrace(p: promise->error!void) void { |
| 224 | 224 | } |
| 225 | 225 | }; |
| 226 | 226 | } |
| 227 | ||
| 228 | test "coroutine in a struct field" { | |
| 229 | const Foo = struct { | |
| 230 | bar: async fn() void, | |
| 231 | }; | |
| 232 | var foo = Foo { | |
| 233 | .bar = simpleAsyncFn2, | |
| 234 | }; | |
| 235 | cancel try async<std.debug.global_allocator> foo.bar(); | |
| 236 | } | |
| 237 | ||
| 238 | async fn simpleAsyncFn2() void { | |
| 239 | suspend; | |
| 240 | } |