From 3a2566991a5dc911e89a2300301cdb241f341089 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sun, 16 Mar 2025 03:46:03 +0800 Subject: [PATCH] Handle nomem in just about everything Signed-off-by: Runxi Yu --- cmd/child/main.ha | 4 ++-- cmd/dnsclient/main.ha | 2 +- cmd/hget/main.ha | 8 ++++---- cmd/httpclient/main.ha | 2 +- cmd/httpserv/main.ha | 6 +++--- cmd/tcpclient/main.ha | 12 ++++++------ cmd/tcpserv/main.ha | 16 ++++++++-------- cmd/timer/main.ha | 2 +- cmd/udpclient/main.ha | 10 +++++----- cmd/udpserv/main.ha | 4 ++-- ev/+linux/io.ha | 14 +++++++------- ev/+linux/loop.ha | 30 +++++++++++++++--------------- ev/+linux/poll.ha | 20 ++++++++++---------- ev/+linux/process.ha | 8 ++++---- ev/+linux/signal.ha | 6 +++--- ev/+linux/socket.ha | 46 +++++++++++++++++++++++----------------------- ev/+linux/timers.ha | 6 +++--- ev/client/http.ha | 10 +++++----- ev/dial/dial.ha | 8 ++++---- ev/dial/ip.ha | 40 ++++++++++++++++++++-------------------- ev/dial/resolve.ha | 42 +++++++++++++++++++++--------------------- ev/dns/dns.ha | 42 +++++++++++++++++++++--------------------- ev/server/http.ha | 16 ++++++++-------- ev/server/server.ha | 4 ++-- diff --git a/cmd/child/main.ha b/cmd/child/main.ha index 7a999e60e21f9f9deeb5dff122d693e7e3a06d24..918b1acc28228393fb831ee188c867c5344f2b92 100644 --- a/cmd/child/main.ha +++ b/cmd/child/main.ha @@ -20,13 +20,13 @@ for (ev::dispatch(&loop, -1)!) void; }; -fn expired(timer: *ev::file) void = { +fn expired(timer: *ev::file) (void | nomem) = { fmt::println("Child timed out, sending SIGTERM")!; const child = ev::getuser(timer): *ev::file; ev::kill(child)!; }; -fn child_exited(child: *ev::file, r: exec::status) void = { +fn child_exited(child: *ev::file, r: exec::status) (void | nomem) = { const exit = exec::exit(&r); fmt::printfln("child exited: {}", exec::exitstr(exit))!; diff --git a/cmd/dnsclient/main.ha b/cmd/dnsclient/main.ha index 8fd721b37806432c912921ba2e12aa6c43074458..d9e9265daec8e3807671da24aa3e5aaa502737b4 100644 --- a/cmd/dnsclient/main.ha +++ b/cmd/dnsclient/main.ha @@ -17,7 +17,7 @@ fn resolvecb( user: nullable *opaque, r: (([]ip::addr, u16) | dial::error), -) void = { +) (void | nomem) = { const loop = user: *ev::loop; defer ev::stop(loop); diff --git a/cmd/hget/main.ha b/cmd/hget/main.ha index 7d4acbc1952d151ad1ac2172c3d4a9bd04783b5a..e4500ca9526d86a0709410f22f1eeb0717f3672b 100644 --- a/cmd/hget/main.ha +++ b/cmd/hget/main.ha @@ -41,7 +41,7 @@ state.exit = os::status::FAILURE; ev::stop(state.loop); }; -fn dialcb(user: nullable *opaque, r: (*ev::file | dial::error)) void = { +fn dialcb(user: nullable *opaque, r: (*ev::file | dial::error)) (void | nomem) = { let state = user: *state; const file = match (r) { case let file: *ev::file => @@ -60,12 +60,12 @@ case let s: str => yield s; case let ip: ip::addr => yield ip::string(ip); - }); + })?; ev::write(file, &writecb, state.buf[..len(s)]); }; -fn writecb(file: *ev::file, r: (size | io::error)) void = { +fn writecb(file: *ev::file, r: (size | io::error)) (void | nomem) = { const state = ev::getuser(file): *state; const z = match (r) { case let z: size => @@ -77,7 +77,7 @@ }; ev::read(file, &readcb, state.buf); }; -fn readcb(file: *ev::file, r: (size | io::EOF | io::error)) void = { +fn readcb(file: *ev::file, r: (size | io::EOF | io::error)) (void | nomem) = { const state = ev::getuser(file): *state; const z = match (r) { case let z: size => diff --git a/cmd/httpclient/main.ha b/cmd/httpclient/main.ha index b5e6528347e821ea1cb635ba304bca104ad5571e..b6cb259549101528c3317beae9860d71abd0f569 100644 --- a/cmd/httpclient/main.ha +++ b/cmd/httpclient/main.ha @@ -20,7 +20,7 @@ export fn main() void = { const loop = ev::newloop()!; defer ev::finish(&loop); - const client = http::newclient("Hare net::http test client"); + const client = http::newclient("Hare net::http test client")!; defer http::client_finish(&client); const targ = uri::parse("http://127.0.0.1:8080")!; diff --git a/cmd/httpserv/main.ha b/cmd/httpserv/main.ha index 6633dbc44ec242423c3fb036f4253490322e622d..cc50a7888031914ef397f6151cbec0215043b6b1 100644 --- a/cmd/httpserv/main.ha +++ b/cmd/httpserv/main.ha @@ -35,7 +35,7 @@ let state = state { loop = &loop, ... }; - const server = server::http_serve(sock, &http_serve, &state); + const server = server::http_serve(sock, &http_serve, &state)!; defer server::server_finish(server); const sig = ev::signal(&loop, &signal, signal::sig::INT, signal::sig::TERM)!; @@ -47,7 +47,7 @@ for (ev::dispatch(&loop, -1)!) void; os::exit(state.exit); }; -fn signal(file: *ev::file, sig: signal::sig) void = { +fn signal(file: *ev::file, sig: signal::sig) (void | nomem) = { log::printfln("Exiting due to {}", signal::signame(sig)); const state = ev::getuser(file): *state; ev::stop(state.loop); @@ -77,7 +77,7 @@ io::copy(&buf, req.body)!; io::seek(&buf, 0, io::whence::SET)!; - http::response_add_header(&rw, "Content-Type", "text/plain"); + http::response_add_header(&rw, "Content-Type", "text/plain")!; http::response_set_body(&rw, &buf); http::response_write(&rw)!; }; diff --git a/cmd/tcpclient/main.ha b/cmd/tcpclient/main.ha index 8b802c9a8c0f3ae0707b7ac8d9b501d7da6d2b1c..36f1feb1963f98d064f23e2a6ff19783a24e28a9 100644 --- a/cmd/tcpclient/main.ha +++ b/cmd/tcpclient/main.ha @@ -42,7 +42,7 @@ for (ev::dispatch(&loop, -1)!) void; }; -fn connected(result: (*ev::file | net::error), user: nullable *opaque) void = { +fn connected(result: (*ev::file | net::error), user: nullable *opaque) (void | nomem) = { const state = user: *state; const sock = match (result) { case let err: net::error => @@ -54,10 +54,10 @@ ev::setuser(sock, state); state.sock = sock; ev::read(state.sock, &sock_read, state.netbuf); - ev::readable(state.stdin, &stdin_readable); + ev::readable(state.stdin, &stdin_readable)?; }; -fn stdin_readable(file: *ev::file) void = { +fn stdin_readable(file: *ev::file) (void | nomem) = { const state = ev::getuser(file): *state; const n = match (io::read(os::stdin_file, state.stdbuf)) { case let n: size => @@ -74,7 +74,7 @@ state.wbuf = state.stdbuf[..n]; ev::write(state.sock, &sock_write, state.wbuf); }; -fn sock_read(file: *ev::file, r: (size | io::EOF | io::error)) void = { +fn sock_read(file: *ev::file, r: (size | io::EOF | io::error)) (void | nomem) = { const state = ev::getuser(file): *state; const n = match (r) { case let n: size => @@ -91,7 +91,7 @@ io::write(os::stdout_file, state.netbuf[..n])!; ev::read(state.sock, &sock_read, state.netbuf); }; -fn sock_write(file: *ev::file, r: (size | io::error)) void = { +fn sock_write(file: *ev::file, r: (size | io::error)) (void | nomem) = { const state = ev::getuser(file): *state; const n = match (r) { case let n: size => @@ -105,6 +105,6 @@ static delete(state.wbuf[..n]); if (len(state.wbuf) != 0) { ev::write(state.sock, &sock_write, state.wbuf); } else { - ev::readable(state.stdin, &stdin_readable); + ev::readable(state.stdin, &stdin_readable)?; }; }; diff --git a/cmd/tcpserv/main.ha b/cmd/tcpserv/main.ha index 5a79ea948fee5c8adcf1cf33717626585697516a..2091f72fb85dc1e57b63a4d8b56296a0e007a48e 100644 --- a/cmd/tcpserv/main.ha +++ b/cmd/tcpserv/main.ha @@ -55,13 +55,13 @@ for (ev::dispatch(&loop, -1)!) void; os::exit(state.exit); }; -fn signal(file: *ev::file, sig: signal::sig) void = { +fn signal(file: *ev::file, sig: signal::sig) (void | nomem) = { log::printfln("Exiting due to {}", signal::signame(sig)); const server = ev::getuser(file): *server; ev::stop(server.loop); }; -fn server_accept(sock: *ev::file, r: (*ev::file | net::error)) void = { +fn server_accept(sock: *ev::file, r: (*ev::file | net::error)) (void | nomem) = { let server = ev::getuser(sock): *server; const sock = match (r) { case let sock: *ev::file => @@ -89,17 +89,17 @@ ev::read(client.sock, &client_read, client.buf); ev::accept(server.sock, &server_accept); }; -fn client_read(sock: *ev::file, r: (size | io::EOF | io::error)) void = { +fn client_read(sock: *ev::file, r: (size | io::EOF | io::error)) (void | nomem) = { const client = ev::getuser(sock): *client; const n = match (r) { case let err: io::error => log::printfln("{}:{}: Error: read: {}", ip::string(client.addr), client.port, io::strerror(err)); - client_close(client); + client_close(client)?; return; case io::EOF => - client_close(client); + client_close(client)?; return; case let n: size => yield n; @@ -108,14 +108,14 @@ client.wbuf = client.buf[..n]; ev::write(client.sock, &client_write, client.wbuf); }; -fn client_write(sock: *ev::file, r: (size | io::error)) void = { +fn client_write(sock: *ev::file, r: (size | io::error)) (void | nomem) = { const client = ev::getuser(sock): *client; const n = match (r) { case let err: io::error => log::printfln("{}:{}: Error: write: {}", ip::string(client.addr), client.port, io::strerror(err)); - client_close(client); + client_close(client)?; return; case let n: size => yield n; @@ -128,7 +128,7 @@ ev::read(client.sock, &client_read, client.buf); }; }; -fn client_close(client: *client) void = { +fn client_close(client: *client) (void | nomem) = { const server = client.server; for (let i = 0z; i < len(server.clients); i += 1) { if (server.clients[i] == client) { diff --git a/cmd/timer/main.ha b/cmd/timer/main.ha index 09867d076b3060be1f4e4eaaf3735d4c172d0374..45a51ab81278d501aad68bf9812e44c213ea77d6 100644 --- a/cmd/timer/main.ha +++ b/cmd/timer/main.ha @@ -12,6 +12,6 @@ for (ev::dispatch(&loop, -1)!) void; }; -fn expired(timer: *ev::file) void = { +fn expired(timer: *ev::file) (void | nomem) = { log::println("timer expired"); }; diff --git a/cmd/udpclient/main.ha b/cmd/udpclient/main.ha index d0c966715d544dbf948fd549f9a0fa5109287ee2..b3f9403020f109fc9924de22b3cfc89580727066 100644 --- a/cmd/udpclient/main.ha +++ b/cmd/udpclient/main.ha @@ -34,12 +34,12 @@ ev::setuser(state.stdin, &state); ev::setuser(state.stdout, &state); ev::setuser(state.sock, &state); - ev::readable(state.stdin, &stdin_readable); + ev::readable(state.stdin, &stdin_readable)!; for (ev::dispatch(&loop, -1)!) void; }; -fn stdin_readable(file: *ev::file) void = { +fn stdin_readable(file: *ev::file) (void | nomem) = { const state = ev::getuser(file): *state; const n = match (io::read(os::stdin_file, state.stdbuf)) { case let n: size => @@ -56,7 +56,7 @@ state.wbuf = state.stdbuf[..n]; ev::send(state.sock, &sock_send, state.wbuf); }; -fn sock_recv(file: *ev::file, r: (size | net::error)) void = { +fn sock_recv(file: *ev::file, r: (size | net::error)) (void | nomem) = { const state = ev::getuser(file): *state; const n = match (r) { case let n: size => @@ -69,7 +69,7 @@ }; io::write(os::stdout_file, state.netbuf[..n])!; }; -fn sock_send(file: *ev::file, r: (size | net::error)) void = { +fn sock_send(file: *ev::file, r: (size | net::error)) (void | nomem) = { const state = ev::getuser(file): *state; const n = match (r) { case let n: size => @@ -84,6 +84,6 @@ if (len(state.wbuf) != 0) { ev::send(state.sock, &sock_send, state.wbuf); } else { ev::recv(state.sock, &sock_recv, state.netbuf); - ev::readable(state.stdin, &stdin_readable); + ev::readable(state.stdin, &stdin_readable)?; }; }; diff --git a/cmd/udpserv/main.ha b/cmd/udpserv/main.ha index e98fc6c906c25b1324111306195b4b0b6caec9de..fc531587e41a679c1c1b198e3991d4b4d19b97cc 100644 --- a/cmd/udpserv/main.ha +++ b/cmd/udpserv/main.ha @@ -39,7 +39,7 @@ log::println("Listening on 127.0.0.1:12345"); for (ev::dispatch(&loop, -1)!) void; }; -fn recv(sock: *ev::file, r: ((size, ip::addr, u16) | net::error)) void = { +fn recv(sock: *ev::file, r: ((size, ip::addr, u16) | net::error)) (void | nomem) = { const state = ev::getuser(sock): *state; const (n, src, port) = match (r) { case let err: net::error => @@ -60,7 +60,7 @@ state.wbuf = state.buf[..n]; ev::sendto(sock, &send, state.wbuf, src, port); }; -fn send(sock: *ev::file, r: (size | net::error)) void = { +fn send(sock: *ev::file, r: (size | net::error)) (void | nomem) = { const state = ev::getuser(sock): *state; const n = match (r) { case let err: net::error => diff --git a/ev/+linux/io.ha b/ev/+linux/io.ha index 1758d60e2e76ad3c72293a364d13197b0ffd4f9f..09dc1ab1916ac7700c6b9e2e2668b71c1252c780 100644 --- a/ev/+linux/io.ha +++ b/ev/+linux/io.ha @@ -2,7 +2,7 @@ use io; use rt; // A callback for a [[read]] or [[readv]] operation. -export type readcb = fn(file: *file, result: (size | io::EOF | io::error)) void; +export type readcb = fn(file: *file, result: (size | io::EOF | io::error)) (void | nomem); // Schedules a read operation on a file object. The provided buffer must be // valid for the duration of the read operation. @@ -27,7 +27,7 @@ ) req = { assert(file.op & op::READV == 0); if (file.flags & fflags::BLOCKING != 0) { const r = io::readv(file.fd, vec...); - cb(file, r); + cb(file, r)!; return req { ... }; }; @@ -46,11 +46,11 @@ file.op &= ~op::READV; file_epoll_ctl(file); if (ev.events & rt::EPOLLHUP != 0) { - cb(file, io::EOF); + cb(file, io::EOF)!; } else { const vec = file.rvec: []io::vector; const r = io::readv(file.fd, vec...); - cb(file, r); + cb(file, r)!; }; }; @@ -62,7 +62,7 @@ file_epoll_ctl(file); }; // A callback for a [[write]] or [[writev]] operation. -export type writecb = fn(file: *file, result: (size | io::error)) void; +export type writecb = fn(file: *file, result: (size | io::error)) (void | nomem); // Schedules a write operation on a file object. The provided buffer must be // valid for the duration of the write operation. @@ -87,7 +87,7 @@ ) req = { assert(file.op & op::WRITEV == 0); if (file.flags & fflags::BLOCKING != 0) { const r = io::writev(file.fd, vec...); - cb(file, r); + cb(file, r)!; return req { ... }; }; @@ -106,7 +106,7 @@ const r = io::writev(file.fd, vec...); const cb = file.cb2: *writecb; file.op &= ~op::WRITEV; file_epoll_ctl(file); - cb(file, r); + cb(file, r)!; }; fn writev_cancel(req: *req) void = { diff --git a/ev/+linux/loop.ha b/ev/+linux/loop.ha index 732f55c73b32a076fef8b2db139480c176794dff..7bbe079cc1f0d73ee476497df3794d8e9f337fd2 100644 --- a/ev/+linux/loop.ha +++ b/ev/+linux/loop.ha @@ -7,7 +7,7 @@ use types; use unix::signal; // Dispatch callback. See [[ondispatch]]. -export type dispatchcb = fn(loop: *loop, user: nullable *opaque) void; +export type dispatchcb = fn(loop: *loop, user: nullable *opaque) (void | nomem); export type ondispatch = struct { cb: *dispatchcb, @@ -109,7 +109,7 @@ // Returns false if the loop has been stopped via [[stop]], or true otherwise. export fn dispatch( loop: *loop, timeout: time::duration, -) (bool | errors::error) = { +) (bool | errors::error | nomem) = { const millis: int = if (timeout == -1) { yield -1; } else if (timeout < 0) { @@ -124,7 +124,7 @@ let todo = loop.dispatch; loop.dispatch = []; for (let dispatch .. todo) { - dispatch.cb(loop, dispatch.user); + dispatch.cb(loop, dispatch.user)?; free(dispatch); }; free(todo); @@ -175,29 +175,29 @@ switch (pending) { case op::NONE => abort("No operation pending for ready object"); case op::READABLE => - readable_ready(file, ev); + readable_ready(file, ev)?; case op::WRITABLE => - writable_ready(file, ev); + writable_ready(file, ev)?; case op::ACCEPT => - accept_ready(file, ev); + accept_ready(file, ev)?; case op::CONNECT_TCP => - connect_tcp_ready(file, ev); + connect_tcp_ready(file, ev)?; case op::CONNECT_UNIX => - connect_unix_ready(file, ev); + connect_unix_ready(file, ev)?; case op::SIGNAL => - signal_ready(file, ev); + signal_ready(file, ev)?; case op::TIMER => - timer_ready(file, ev); + timer_ready(file, ev)?; case op::SENDTO => - sendto_ready(file, ev); + sendto_ready(file, ev)?; case op::RECVFROM => - recvfrom_ready(file, ev); + recvfrom_ready(file, ev)?; case op::SEND => - send_ready(file, ev); + send_ready(file, ev)?; case op::RECV => - recv_ready(file, ev); + recv_ready(file, ev)?; case op::WAIT => - wait_ready(file, ev); + wait_ready(file, ev)?; case => assert(pending & ~(op::READV | op::WRITEV) == 0); }; diff --git a/ev/+linux/poll.ha b/ev/+linux/poll.ha index 33b77eafd1991103db9c09d5dd99585bbb7750b9..7b13a70e267b15aceabea8ae73f06cea6c53073c 100644 --- a/ev/+linux/poll.ha +++ b/ev/+linux/poll.ha @@ -1,17 +1,17 @@ use rt; // A callback for a [[readable]] operation. -export type readablecb = fn(file: *file) void; +export type readablecb = fn(file: *file) (void | nomem); // Executes the callback when a given file is readable. Cannot be combined with // [[read]] or [[readv]]. export fn readable( file: *file, cb: *readablecb, -) req = { +) (req | nomem)= { assert(file.op & op::READABLE == 0 && file.op & op::READV == 0); if (file.flags & fflags::BLOCKING != 0) { - cb(file); + cb(file)?; return req { ... }; }; @@ -21,13 +21,13 @@ file_epoll_ctl(file); return mkreq(&readable_cancel, file); }; -fn readable_ready(file: *file, ev: *rt::epoll_event) void = { +fn readable_ready(file: *file, ev: *rt::epoll_event) (void | nomem) = { assert(file.op & op::READABLE != 0); assert(file.cb != null); const cb = file.cb: *readablecb; file.op &= ~op::READABLE; file_epoll_ctl(file); - cb(file); + cb(file)?; }; fn readable_cancel(req: *req) void = { @@ -38,17 +38,17 @@ file_epoll_ctl(file); }; // A callback for a [[writable]] operation. -export type writablecb = fn(file: *file) void; +export type writablecb = fn(file: *file) (void | nomem); // Executes the callback when a given file is writable. Cannot be combined with // [[write]] or [[writev]]. export fn writable( file: *file, cb: *writablecb, -) req = { +) (req | nomem)= { assert(file.op & op::WRITABLE == 0 && file.op & op::WRITEV == 0); if (file.flags & fflags::BLOCKING != 0) { - cb(file); + cb(file)?; return req { ... }; }; @@ -58,13 +58,13 @@ file_epoll_ctl(file); return mkreq(&writable_cancel, file); }; -fn writable_ready(file: *file, ev: *rt::epoll_event) void = { +fn writable_ready(file: *file, ev: *rt::epoll_event) (void | nomem) = { assert(file.op & op::WRITABLE != 0); assert(file.cb != null); const cb = file.cb: *writablecb; file.op &= ~op::WRITABLE; file_epoll_ctl(file); - cb(file); + cb(file)?; }; fn writable_cancel(req: *req) void = { diff --git a/ev/+linux/process.ha b/ev/+linux/process.ha index 18f23ba91bd980b74d1e50f348a077dc94fb1607..37a1d8751ff467de41707f8e7460e934b5012e94 100644 --- a/ev/+linux/process.ha +++ b/ev/+linux/process.ha @@ -33,7 +33,7 @@ return register(loop, pidfd); }; // A callback for a [[wait]] operation. -export type waitcb = fn(file: *file, result: exec::status) void; +export type waitcb = fn(file: *file, result: exec::status) (void | nomem); // Waits for a process to exit. After the callback is run, the [[file]] is // closed and unregistered from the event loop and may not be used again. @@ -60,7 +60,7 @@ // Calls [[rt::waitid]] with the given options. If successful, calls the // callback and cleans up the file (and returns void). If unsuccessful, returns // the error. -fn do_waitid(proc: *file, cb: *waitcb, options: int = 0) (void | rt::errno) = { +fn do_waitid(proc: *file, cb: *waitcb, options: int = 0) (void | rt::errno | nomem) = { def WAIT_OPTIONS = rt::WEXITED | rt::WSTOPPED | rt::WCONTINUED; let si = rt::siginfo { ... }; @@ -89,7 +89,7 @@ status = status, ... }; rusage(&st, &ru); - cb(proc, st); + cb(proc, st)?; close(proc); }; @@ -100,7 +100,7 @@ proc.op &= ~op::WAIT; file_epoll_ctl(proc); }; -fn wait_ready(proc: *file, ev: *rt::epoll_event) void = { +fn wait_ready(proc: *file, ev: *rt::epoll_event) (void | nomem) = { assert(proc.op & op::WAIT != 0); assert(proc.cb != null); const cb = proc.cb: *waitcb; diff --git a/ev/+linux/signal.ha b/ev/+linux/signal.ha index 1aee689874c29fef3aba99cded58a6c186cf2f38..970aff6e8f2d238c69abf489308e0b3ef855e834 100644 --- a/ev/+linux/signal.ha +++ b/ev/+linux/signal.ha @@ -4,7 +4,7 @@ use rt; use unix::signal; // Callback function for [[signal]] operations. -export type signalcb = fn(file: *file, sig: signal::sig) void; +export type signalcb = fn(file: *file, sig: signal::sig) (void | nomem); // Registers a signal handler with this event loop. The signals specified will // be masked so they are only raised via the provided callback. Closing this @@ -42,10 +42,10 @@ }; signal::unblock(signals...); }; -fn signal_ready(file: *file, ev: *rt::epoll_event) void = { +fn signal_ready(file: *file, ev: *rt::epoll_event) (void | nomem) = { assert(file.op == op::SIGNAL); assert(file.cb != null); const cb = file.cb: *signalcb; const info = signal::read(file.fd)!; - cb(file, info.signo); + cb(file, info.signo)?; }; diff --git a/ev/+linux/socket.ha b/ev/+linux/socket.ha index a860b97400c59e99c6b20e14c3c7b74aeaebfbb8..2ea7edda745550bb03d7f7d2baa5f18eda61bdd8 100644 --- a/ev/+linux/socket.ha +++ b/ev/+linux/socket.ha @@ -53,7 +53,7 @@ const file = register(loop, sock)?; return file; }; -export type connectcb = fn(result: (*file | net::error), user: nullable *opaque) void; +export type connectcb = fn(result: (*file | net::error), user: nullable *opaque) (void | nomem); // Creates a socket and connects to a given IP address and port over TCP. // @@ -152,7 +152,7 @@ fn connect_tcp_ready( sock: *file, ev: *rt::epoll_event, -) void = { +) (void | nomem) = { assert(sock.op == op::CONNECT_TCP); assert(ev.events & rt::EPOLLOUT != 0); assert(sock.cb != null); @@ -163,21 +163,21 @@ let errno = 0i, optsz = size(int): u32; rt::getsockopt(sock.fd, rt::SOL_SOCKET, rt::SO_ERROR, &errno, &optsz)!; if (errno != 0) { - cb(errors::errno(errno), sock.user); + cb(errors::errno(errno), sock.user)?; close(sock); } else { // XXX: If the user puts NONBLOCK into the opts provided at // [[connect_tcp]] we could try to preserve that here const fl = rt::fcntl(sock.fd, rt::F_GETFL, void)!; rt::fcntl(sock.fd, rt::F_SETFL, fl & ~rt::O_NONBLOCK)!; - cb(sock, sock.user); + cb(sock, sock.user)?; }; }; fn connect_unix_ready( sock: *file, ev: *rt::epoll_event, -) void = { +) (void | nomem) = { assert(sock.op == op::CONNECT_UNIX); assert(ev.events & rt::EPOLLOUT != 0); assert(sock.cb != null); @@ -188,14 +188,14 @@ let errno = 0i, optsz = size(int): u32; rt::getsockopt(sock.fd, rt::SOL_SOCKET, rt::SO_ERROR, &errno, &optsz)!; if (errno != 0) { - cb(errors::errno(errno), sock.user); + cb(errors::errno(errno), sock.user)?; close(sock); } else { // XXX: If the user puts NONBLOCK into the opts provided at // [[connect_unix]] we could try to preserve that here const fl = rt::fcntl(sock.fd, rt::F_GETFL, void)!; rt::fcntl(sock.fd, rt::F_SETFL, fl & ~rt::O_NONBLOCK)!; - cb(sock, sock.user); + cb(sock, sock.user)?; }; }; @@ -214,7 +214,7 @@ file_epoll_ctl(sock); }; // A callback for an [[accept]] operation. -export type acceptcb = fn(file: *file, result: (*file | net::error)) void; +export type acceptcb = fn(file: *file, result: (*file | net::error)) (void | nomem); // Schedules an accept operation on a socket. export fn accept( @@ -237,7 +237,7 @@ fn accept_ready( sock: *file, ev: *rt::epoll_event, -) void = { +) (void | nomem) = { assert(sock.op == op::ACCEPT); assert(ev.events & rt::EPOLLIN != 0); assert(sock.cb != null); @@ -250,9 +250,9 @@ match (r) { case let fd: net::socket => // TODO: Bubble up errors from here? const file = register(sock.ev, fd)!; - cb(sock, file); + cb(sock, file)?; case let err: net::error => - cb(sock, err); + cb(sock, err)?; }; }; @@ -271,7 +271,7 @@ // of the sender. export type recvfromcb = fn( file: *file, r: ((size, ip::addr, u16) | net::error), -) void; +) (void | nomem); // Schedules a receive operation on a socket. export fn recvfrom( @@ -290,7 +290,7 @@ fn recvfrom_ready( sock: *file, ev: *rt::epoll_event, -) void = { +) (void | nomem) = { assert(sock.op == op::RECVFROM); assert(sock.cb != null); const cb = sock.cb: *recvfromcb; @@ -300,9 +300,9 @@ let src: ip::addr = ip::ANY_V4, port = 0u16; match (udp::recvfrom(sock.fd, sock.sendrecv.rbuf, &src, &port)) { case let err: net::error => - cb(sock, err); + cb(sock, err)?; case let n: size => - cb(sock, (n, src, port)); + cb(sock, (n, src, port))?; }; }; @@ -314,7 +314,7 @@ file_epoll_ctl(sock); }; // Callback for a [[recv]] operation. -export type recvcb = fn(file: *file, r: (size | net::error)) void; +export type recvcb = fn(file: *file, r: (size | net::error)) (void | nomem); // Schedules a receive operation on a (connected) socket. export fn recv( @@ -333,7 +333,7 @@ fn recv_ready( sock: *file, ev: *rt::epoll_event, -) void = { +) (void | nomem) = { assert(sock.op == op::RECV); assert(sock.cb != null); const cb = sock.cb: *recvcb; @@ -341,7 +341,7 @@ sock.op = op::NONE; file_epoll_ctl(sock); const r = udp::recv(sock.fd, sock.sendrecv.rbuf); - cb(sock, r); + cb(sock, r)?; }; fn recv_cancel(req: *req) void = { @@ -352,7 +352,7 @@ file_epoll_ctl(sock); }; // Callback for a [[send]] or [[sendto]] operation. -export type sendtocb = fn(file: *file, r: (size | net::error)) void; +export type sendtocb = fn(file: *file, r: (size | net::error)) (void | nomem); // Schedules a send operation on a (connected) socket. export fn send( @@ -371,7 +371,7 @@ fn send_ready( sock: *file, ev: *rt::epoll_event, -) void = { +) (void | nomem) = { assert(sock.op == op::SEND); assert(sock.cb != null); const cb = sock.cb: *sendtocb; @@ -379,7 +379,7 @@ sock.op = op::NONE; file_epoll_ctl(sock); const r = udp::send(sock.fd, sock.sendrecv.sbuf); - cb(sock, r); + cb(sock, r)?; }; fn send_cancel(req: *req) void = { @@ -410,7 +410,7 @@ fn sendto_ready( sock: *file, ev: *rt::epoll_event, -) void = { +) (void | nomem) = { assert(sock.op == op::SENDTO); assert(sock.cb != null); const cb = sock.cb: *sendtocb; @@ -423,7 +423,7 @@ sock.sendrecv.sbuf, sock.sendrecv.dest, sock.sendrecv.port, ); - cb(sock, r); + cb(sock, r)?; }; fn sendto_cancel(req: *req) void = { diff --git a/ev/+linux/timers.ha b/ev/+linux/timers.ha index 2d400ce6133f004eda6e5170f0b4ade1a2aa8376..ff2591cadfe6de9dcb532d4d02288548d25ca70c 100644 --- a/ev/+linux/timers.ha +++ b/ev/+linux/timers.ha @@ -4,7 +4,7 @@ use rt; use time; // A callback which executes when a timer expires. -export type timercb = fn(file: *file) void; +export type timercb = fn(file: *file) (void | nomem); // Creates a new timer. By default, this timer never expires; configure it with // [[timer_configure]]. @@ -45,7 +45,7 @@ }; rt::timerfd_settime(timer.fd, 0, &spec, null)!; }; -fn timer_ready(timer: *file, ev: *rt::epoll_event) void = { +fn timer_ready(timer: *file, ev: *rt::epoll_event) (void | nomem) = { assert(timer.op == op::TIMER); let buf: [8]u8 = [0...]; match (io::read(timer.fd, buf)) { @@ -61,5 +61,5 @@ }; assert(timer.cb != null); const cb = timer.cb: *timercb; - cb(timer); + cb(timer)?; }; diff --git a/ev/client/http.ha b/ev/client/http.ha index 6e1d4d33bd17b3fe067e5de36f05c9002469e970..5b7d030f16d13eb374e93d675e583a5647f64085 100644 --- a/ev/client/http.ha +++ b/ev/client/http.ha @@ -23,13 +23,13 @@ reqcli: *http::client, req: *http::request, cb: *http_donecb, user: nullable *opaque -) (ev::req | dial::error | io::error) = { +) (ev::req | dial::error | io::error | nomem) = { const cli = alloc(client { cb = cb, user = user, buf = memio::dynamic(), ... - }); + })?; http::request_write_internal(&cli.buf, req, reqcli)?; const req = dial::dial_uri( loop, @@ -61,7 +61,7 @@ ev::cancel(&cli.req); client_close(cli); }; -fn http_dialed(user: nullable *opaque, r: (*ev::file | dial::error)) void = { +fn http_dialed(user: nullable *opaque, r: (*ev::file | dial::error)) (void | nomem) = { const cli = user: *client; cli.req = ev::req { ... }; @@ -80,7 +80,7 @@ cli.wbuf = memio::buffer(&cli.buf: *memio::stream); ev::write(file, &http_write, cli.wbuf); }; -fn http_write(sock: *ev::file, r: (size | io::error)) void = { +fn http_write(sock: *ev::file, r: (size | io::error)) (void | nomem) = { const cli = ev::getuser(sock): *client; const n = match (r) { @@ -102,7 +102,7 @@ memio::reset(&cli.buf); ev::read(sock, &http_read, cli.rbuf); }; -fn http_read(sock: *ev::file, r: (size | io::EOF | io::error)) void = { +fn http_read(sock: *ev::file, r: (size | io::EOF | io::error)) (void | nomem) = { const cli = ev::getuser(sock): *client; const cb = cli.cb: *http_donecb; diff --git a/ev/dial/dial.ha b/ev/dial/dial.ha index 1541495470ac8aee258d92adeaca9a4fea51628f..735f29da495f9a265e2d082c53781f21bc7f7216 100644 --- a/ev/dial/dial.ha +++ b/ev/dial/dial.ha @@ -6,7 +6,7 @@ use net::ip; use net::uri; // Callback for a [[dial]] operation. -export type dialcb = fn(user: nullable *opaque, r: (*ev::file | error)) void; +export type dialcb = fn(user: nullable *opaque, r: (*ev::file | error)) (void | nomem); // Dials a remote address, establishing a connection and returning the resulting // [[net::socket]] to the callback. The proto parameter should be the transport @@ -59,13 +59,13 @@ const port: fmt::formattable = if (uri.port != 0) uri.port else ""; let addr = match (uri.host) { case let host: str => - yield fmt::bsprintf(addr, "{}{}{}", host, colon, port); + yield fmt::bsprintf(addr, "{}{}{}", host, colon, port)?; case let ip: ip::addr4 => const host = ip::string(ip); - yield fmt::bsprintf(addr, "{}{}{}", host, colon, port); + yield fmt::bsprintf(addr, "{}{}{}", host, colon, port)?; case let ip: ip::addr6 => const host = ip::string(ip); - yield fmt::bsprintf(addr, "[{}]{}{}", host, colon, port); + yield fmt::bsprintf(addr, "[{}]{}{}", host, colon, port)?; }; return dial(loop, proto, addr, uri.scheme, cb, user); diff --git a/ev/dial/ip.ha b/ev/dial/ip.ha index 9399a16d275b61f663bbcb8fed529b3d6ae98984..bbfd87946c08c193f29530468db55ba5dbec3da8 100644 --- a/ev/dial/ip.ha +++ b/ev/dial/ip.ha @@ -51,29 +51,29 @@ fn dial_tcp_resolvecb( user: nullable *opaque, r: (([]ip::addr, u16) | error), -) void = { +) (void | nomem) = { let state = user: *tcp_dialer; state.req = ev::req { ... }; const (ip, port) = match (r) { case let r: ([]ip::addr, u16) => yield r; case let err: error => - dial_tcp_complete(state, err); + dial_tcp_complete(state, err)?; return; }; state.ip = ip; state.port = port; - dial_tcp_connect(state); + dial_tcp_connect(state)?; }; -fn dial_tcp_connect(state: *tcp_dialer) void = { +fn dial_tcp_connect(state: *tcp_dialer) (void | nomem) = { const req = match (ev::connect_tcp(state.loop, &dial_tcp_connectcb, state.ip[state.n], state.port, state)) { case let err: (net::error | errors::error) => - dial_tcp_complete(state, err); + dial_tcp_complete(state, err)?; return; case let req: ev::req => yield req; @@ -84,22 +84,22 @@ fn dial_tcp_connectcb( r: (*ev::file | net::error), user: nullable *opaque, -) void = { +) (void | nomem) = { let state = user: *tcp_dialer; match (r) { case let sock: *ev::file => ev::setuser(sock, null); - dial_tcp_complete(state, sock); + dial_tcp_complete(state, sock)?; return; case let err: net::error => if (err is errors::netunreachable) { state.n += 1; if (state.n < len(state.ip)) { - dial_tcp_connect(state); + dial_tcp_connect(state)?; return; }; }; - dial_tcp_complete(state, err); + dial_tcp_complete(state, err)?; }; }; @@ -110,12 +110,12 @@ free(state.ip); free(state); }; -fn dial_tcp_complete(state: *tcp_dialer, r: (*ev::file | error)) void = { +fn dial_tcp_complete(state: *tcp_dialer, r: (*ev::file | error)) (void | nomem) = { const cb = state.cb; const user = state.user; free(state.ip); free(state); - cb(user, r); + cb(user, r)?; }; type udp_dialer = struct { @@ -156,23 +156,23 @@ fn dial_udp_resolvecb( user: nullable *opaque, r: (([]ip::addr, u16) | error), -) void = { +) (void | nomem) = { let state = user: *udp_dialer; state.req = ev::req { ... }; const (ip, port) = match (r) { case let r: ([]ip::addr, u16) => yield r; case let err: error => - dial_udp_complete(state, err); + dial_udp_complete(state, err)?; return; }; state.ip = ip; state.port = port; - dial_udp_connect(state); + dial_udp_connect(state)?; }; -fn dial_udp_connect(state: *udp_dialer) void = { +fn dial_udp_connect(state: *udp_dialer) (void | nomem) = { for (true) { match (ev::connect_udp(state.loop, state.ip[state.n], state.port)) { case let err: net::error => @@ -182,10 +182,10 @@ if (state.n < len(state.ip)) { continue; }; }; - dial_udp_complete(state, err); + dial_udp_complete(state, err)?; break; case let err: errors::error => - dial_udp_complete(state, err); + dial_udp_complete(state, err)?; if (err is errors::netunreachable) { state.n += 1; if (state.n < len(state.ip)) { @@ -194,7 +194,7 @@ }; }; break; case let sock: *ev::file => - dial_udp_complete(state, sock); + dial_udp_complete(state, sock)?; break; }; }; @@ -207,10 +207,10 @@ free(state.ip); free(state); }; -fn dial_udp_complete(state: *udp_dialer, r: (*ev::file | error)) void = { +fn dial_udp_complete(state: *udp_dialer, r: (*ev::file | error)) (void | nomem) = { const cb = state.cb; const user = state.user; free(state.ip); free(state); - cb(user, r); + cb(user, r)?; }; diff --git a/ev/dial/resolve.ha b/ev/dial/resolve.ha index d828724def216cdb655f844f7fb2a149496e2bad..0437942db4841520ee1af4965fb9e28fdd94628e 100644 --- a/ev/dial/resolve.ha +++ b/ev/dial/resolve.ha @@ -12,7 +12,7 @@ // Callback from a [[resolve]] operation. export type resolvecb = fn( user: nullable *opaque, r: (([]ip::addr, u16) | error), -) void; +) (void | nomem); type resolve_state = struct { user: nullable *opaque, @@ -37,7 +37,7 @@ addr: str, service: str, cb: *resolvecb, user: nullable *opaque = null -) (ev::req | error) = { +) (ev::req | error | nomem) = { // TODO: Reduce duplication with net::dial let state = alloc(resolve_state { cb = cb, @@ -49,12 +49,12 @@ const (addr, port) = match (dial::splitaddr(addr, service)) { case let svc: (str, u16) => yield svc; case dial::invalid_address => - resolve_finish(state, invalid_address); + resolve_finish(state, invalid_address)?; return ev::req { ... }; }; if (service == "unknown" && port == 0) { - resolve_finish(state, unknown_service); + resolve_finish(state, unknown_service)?; return ev::req { ... }; }; @@ -71,7 +71,7 @@ // - Consult /etc/services // - Fetch the SRV record if (port == 0) { - resolve_finish(state, unknown_service); + resolve_finish(state, unknown_service)?; return ev::req { ... }; }; @@ -80,10 +80,10 @@ case let addr: ip::addr => let addrs: []ip::addr = []; match (append(addrs, addr)) { case void => - resolve_finish(state, (addrs, port)); + resolve_finish(state, (addrs, port))?; return ev::req { ... }; case nomem => - resolve_finish(state, nomem); + resolve_finish(state, nomem)?; return nomem; }; case ip::invalid => yield; @@ -93,11 +93,11 @@ const addrs = match (hosts::lookup(addr)) { case let addrs: []ip::addr => yield addrs; case let e: hosts::error => - resolve_finish(state, nomem); + resolve_finish(state, nomem)?; return e; }; if (len(addrs) != 0) { - resolve_finish(state, (addrs, port)); + resolve_finish(state, (addrs, port))?; return ev::req { ... }; }; @@ -168,14 +168,14 @@ ok = true; return ev::mkreq(&resolve_cancel, state); }; -fn resolve_finish(st: *resolve_state, r: (([]ip::addr, u16) | error)) void = { +fn resolve_finish(st: *resolve_state, r: (([]ip::addr, u16) | error)) (void | nomem) = { const user = st.user; const cb = st.cb; if (r is error) { free(st.ip); }; free(st); - cb(user, r); + cb(user, r)?; }; fn resolve_cancel(req: *ev::req) void = { @@ -186,25 +186,25 @@ free(state.ip); free(state); }; -fn query_cb_v4(user: nullable *opaque, r: (*dns::message | dns::error | nomem)) void = { +fn query_cb_v4(user: nullable *opaque, r: (*dns::message | dns::error | nomem)) (void | nomem) = { let state = user: *resolve_state; state.r4 = ev::req { ... }; match (r) { case let err: dns::error => ev::cancel(&state.r6); - resolve_finish(state, err); + resolve_finish(state, err)?; return; case nomem => ev::cancel(&state.r6); - resolve_finish(state, nomem); + resolve_finish(state, nomem)?; return; case let msg: *dns::message => match (collect_answers(&state.ip, &msg.answers)) { case void => void; case nomem => ev::cancel(&state.r6); - resolve_finish(state, nomem); + resolve_finish(state, nomem)?; return; }; state.nq += 1; @@ -213,28 +213,28 @@ if (state.nq < 2) { return; }; - resolve_finish(state, (state.ip, state.port)); + resolve_finish(state, (state.ip, state.port))?; }; -fn query_cb_v6(user: nullable *opaque, r: (*dns::message | dns::error | nomem)) void = { +fn query_cb_v6(user: nullable *opaque, r: (*dns::message | dns::error | nomem)) (void | nomem) = { let state = user: *resolve_state; state.r6 = ev::req { ... }; match (r) { case let err: dns::error => ev::cancel(&state.r4); - resolve_finish(state, err); + resolve_finish(state, err)?; return; case nomem => ev::cancel(&state.r4); - resolve_finish(state, nomem); + resolve_finish(state, nomem)?; return; case let msg: *dns::message => match (collect_answers(&state.ip, &msg.answers)) { case void => void; case nomem => ev::cancel(&state.r4); - resolve_finish(state, nomem); + resolve_finish(state, nomem)?; return; }; state.nq += 1; @@ -243,7 +243,7 @@ if (state.nq < 2) { return; }; - resolve_finish(state, (state.ip, state.port)); + resolve_finish(state, (state.ip, state.port))?; }; fn collect_answers(addrs: *[]ip::addr, answers: *[]dns::rrecord) (void | nomem) = { diff --git a/ev/dns/dns.ha b/ev/dns/dns.ha index 52f86d35745005ddbebe41fa34d7ef128f9afd7f..951dde4f3c8ec86e7c1df457e554801d011288e5 100644 --- a/ev/dns/dns.ha +++ b/ev/dns/dns.ha @@ -17,7 +17,7 @@ // Callback for a [[query]] operation. export type querycb = fn( user: nullable *opaque, r: (*dns::message | dns::error | nomem), -) void; +) (void | nomem); type qstate = struct { // Event loop objects @@ -131,10 +131,10 @@ free(q.rbuf); free(q); }; -fn query_complete(q: *qstate, r: (*dns::message | dns::error | nomem)) void = { +fn query_complete(q: *qstate, r: (*dns::message | dns::error | nomem)) (void | nomem) = { const cb = q.cb; const user = q.user; - cb(user, r); + cb(user, r)?; match (r) { case let msg: *dns::message => dns::message_free(msg); @@ -143,17 +143,17 @@ }; query_destroy(q); }; -fn timeoutcb(file: *ev::file) void = { +fn timeoutcb(file: *ev::file) (void | nomem) = { const q = ev::getuser(file): *qstate; - query_complete(q, errors::timeout); + query_complete(q, errors::timeout)?; }; -fn qrecvcb(file: *ev::file, r: ((size, ip::addr, u16) | net::error)) void = { +fn qrecvcb(file: *ev::file, r: ((size, ip::addr, u16) | net::error)) (void | nomem) = { const q = ev::getuser(file): *qstate; match (qrecv(q, file, r)) { case void => void; case let r: (*dns::message | dns::error) => - query_complete(q, r); + query_complete(q, r)?; }; }; @@ -169,7 +169,7 @@ const (z, addr, port) = match (r) { case let r: (size, ip::addr, u16) => yield r; case let err: net::error => - query_complete(q, err); + query_complete(q, err)?; return; }; @@ -214,14 +214,14 @@ return err: net::error; }; }; -fn qconnected(result: (*ev::file | net::error), user: nullable *opaque) void = { +fn qconnected(result: (*ev::file | net::error), user: nullable *opaque) (void | nomem) = { const q = user: *qstate; q.r4 = ev::req { ... }; const sock = match (result) { case let file: *ev::file => yield file; case let err: net::error => - query_complete(q, err); + query_complete(q, err)?; return; }; @@ -236,7 +236,7 @@ io::mkvector(q.zbuf), io::mkvector(q.query[..q.qlen])); }; -fn qtcp_write_cb(file: *ev::file, result: (size | io::error)) void = { +fn qtcp_write_cb(file: *ev::file, result: (size | io::error)) (void | nomem) = { const q = ev::getuser(file): *qstate; q.r4 = ev::req { ... }; match (result) { @@ -247,7 +247,7 @@ // the request should make it to the TCP buffer in a single // writev call. assert(z: u16 == q.qlen + 2); case let err: io::error => - query_complete(q, err); + query_complete(q, err)?; }; q.r4 = ev::read(file, &qtcp_readlength_cb, q.zbuf); @@ -256,19 +256,19 @@ fn qtcp_readlength_cb( file: *ev::file, result: (size | io::EOF | io::error), -) void = { +) (void | nomem) = { const q = ev::getuser(file): *qstate; match (result) { case let z: size => if (z != 2) { - query_complete(q, dns::format); + query_complete(q, dns::format)?; return; }; case let err: io::error => - query_complete(q, err); + query_complete(q, err)?; return; case io::EOF => - query_complete(q, dns::format); + query_complete(q, dns::format)?; return; }; @@ -278,7 +278,7 @@ q.rbuf = match (alloc([0u8...], rlen)) { case let rbuf: []u8 => yield rbuf; case nomem => - query_complete(q, nomem); + query_complete(q, nomem)?; return; }; q.r4 = ev::read(file, &qtcp_readdata_cb, q.rbuf); @@ -287,14 +287,14 @@ fn qtcp_readdata_cb( file: *ev::file, result: (size | io::EOF | io::error), -) void = { +) (void | nomem) = { const q = ev::getuser(file): *qstate; q.r4 = ev::req { ... }; match (result) { case let z: size => const rlen = z: u16; if (q.rbuf_valid + rlen > q.rid) { - query_complete(q, dns::format); + query_complete(q, dns::format)?; return; }; q.rbuf_valid += rlen; @@ -310,10 +310,10 @@ }; const resp = match (dns::decode(q.rbuf[..q.rbuf_valid])) { case dns::format => - query_complete(q, dns::format); + query_complete(q, dns::format)?; return; case let msg: *dns::message => yield msg; }; - query_complete(q, resp); + query_complete(q, resp)?; }; diff --git a/ev/server/http.ha b/ev/server/http.ha index c39f4bdee8f9b170218f88d29cb8637e46f4294f..3f8bed6afc8d93e854cc15ff15c2042fe59f0637 100644 --- a/ev/server/http.ha +++ b/ev/server/http.ha @@ -19,14 +19,14 @@ export fn http_serve( sock: *ev::file, cb: *http_servecb, user: nullable *opaque, -) *server = { - const serv = newserver(sock, cb, user); +) (*server | nomem) = { + const serv = newserver(sock, cb, user)?; ev::setuser(sock, serv); ev::accept(sock, &http_accept); return serv; }; -fn http_accept(sock: *ev::file, r: (*ev::file | net::error)) void = { +fn http_accept(sock: *ev::file, r: (*ev::file | net::error)) (void | nomem) = { const server = ev::getuser(sock): *server; const sock = match (r) { @@ -40,16 +40,16 @@ const client = newclient( server, sock, - ); + )?; ev::setuser(client.sock, client); ev::read(client.sock, &http_read, client.rbuf); - append(server.clients, client); + append(server.clients, client)?; ev::accept(server.sock, &http_accept); }; -fn http_read(sock: *ev::file, r: (size | io::EOF | io::error)) void = { +fn http_read(sock: *ev::file, r: (size | io::EOF | io::error)) (void | nomem) = { const client = ev::getuser(sock): *server_client; const n = match (r) { @@ -86,7 +86,7 @@ const resp = http::response { version = (1, 1), status = http::STATUS_OK, - reason = strings::dup(http::status_reason(http::STATUS_OK)), + reason = strings::dup(http::status_reason(http::STATUS_OK))?, header = [], body = io::empty, }; @@ -103,7 +103,7 @@ client.wbuf = memio::buffer(&client.buf); ev::write(client.sock, &http_write, client.wbuf); }; -fn http_write(sock: *ev::file, r: (size | io::error)) void = { +fn http_write(sock: *ev::file, r: (size | io::error)) (void | nomem) = { const client = ev::getuser(sock): *server_client; const n = match (r) { diff --git a/ev/server/server.ha b/ev/server/server.ha index 2d5c6abbce357b17374bf5daa878b5dcbb412455..52b8f1f021d79817bbde582f262591ac438b1bbb 100644 --- a/ev/server/server.ha +++ b/ev/server/server.ha @@ -19,7 +19,7 @@ wbuf: []u8, buf: memio::stream, }; -export fn newserver(sock: *ev::file, cb: *opaque, user: nullable *opaque) *server = { +export fn newserver(sock: *ev::file, cb: *opaque, user: nullable *opaque) (*server | nomem) = { return alloc(server { sock = sock, cb = cb, @@ -36,7 +36,7 @@ }; free(serv); }; -export fn newclient(serv: *server, sock: *ev::file) *server_client = { +export fn newclient(serv: *server, sock: *ev::file) (*server_client | nomem) = { return alloc(server_client { server = serv, sock = sock, -- 2.48.1