diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-09-07 23:24:04 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-09-07 23:24:04 -0700 |
commit | 7f32442862bfc785e613af33d48d1a4a4dae8835 (patch) | |
tree | 95d693bbecd8193f9bb91b2667ec7d3613a74373 /socket.c | |
parent | e9c5a283537e9d7a0722189dbaf295d9f684a7e8 (diff) | |
download | txr-7f32442862bfc785e613af33d48d1a4a4dae8835.tar.gz txr-7f32442862bfc785e613af33d48d1a4a4dae8835.tar.bz2 txr-7f32442862bfc785e613af33d48d1a4a4dae8835.zip |
exceptions: hack to store errno in string object.
Basic idea: when we throw an exception that pertains to a
system error which has an errno code, we can stick the errno
into the memory area of the character string, into the wchar_t
that immediately follows the null terminator. We can do this
because strings track their actual allocation size.
A pair of setter/getter functions to set and retrieve this
value are provided, and all functions in the code which can
set such a code are updated to do so, simply by calling the
newly added uw_ethrowf that drop-in replaces for uw_throwf.
* lib.[ch] (string_set_code, string_get_code): New functions.
* unwind.[ch] (uw_ethrowf): New function.
* eval.c (eval_init): Register string-set-code and
string-get-code intrinsics.
* ftw.c (ftw_wrap): Switch to uw_ethrowf.
* parser.c (open_txr_file): Likewise.
* socket.c (dgram_overflow): Store the ENOBUFS error in errno,
and use uw_ethrowf instead uw_throwf.
(dgram_get_byte_callback, dgram_flush, sock_bind, to_connect,
open_sockfd, sock_connect, sock_listen, sock_accept,
sock_shutdown, sock_timeout, socketpair_wrap): Switch to
uw_ethrowf.
* stream.c (dev_null_get_fd, stdio_maybe_read_error,
stdio_maybe_error, stdio_close, pipe_close, open_directory,
open_file, open_fileno, open_tail, fds_subst,
open_subprocess, open_command, remove_path, rename_path,
tmpfile_wrap, mkdtemp_wrap, mkstemp_wrap): Switch to uw_ethrowf.
* sysif.c (mkdir_wrap, ensure_dir, chdir_wrap, getcwd_wrap,
rmdir_wrap, mknod_wrap, mkfifo_wrap, chmod_wrap, do_chown,
symlink_wrap, link_wrap, readlink_wrap, close_wrap, val
exec_wrap, stat_impl, do_utimes, pipe_wrap, poll_wrap,
getgroups_wrap, setuid_wrap, seteuid_wrap, setgid_wrap,
setegid_wrap, setgroups_wrap, getresuid_wrap, setresuid_wrap,
setresgid_wrap, crypt_wrap, uname_wrap, opendir_wrap,
getrlimit_wrap, setrlimit_wrap): Likewise.
* termios.c (tcgetattr_wrap, tcsetattr_wrap, tcsendbreak_wrap,
tcdrain_wrap, tcflush_wrap, tcflow_wrap): Likewise.
* tests/018/errno.tl: New file.
* txr.1: Documented.
* stdlib/doc-syms.tl: Updated.
Diffstat (limited to 'socket.c')
-rw-r--r-- | socket.c | 70 |
1 files changed, 35 insertions, 35 deletions
@@ -382,8 +382,8 @@ static void dgram_overflow(val stream) * increasing the datagram size. */ struct dgram_stream *d = coerce(struct dgram_stream *, stream->co.handle); - d->err = ENOBUFS; - uw_throwf(socket_error_s, lit("dgram write overflow on ~s"), stream, nao); + errno = d->err = ENOBUFS; + uw_ethrowf(socket_error_s, lit("dgram write overflow on ~s"), stream, nao); } static int dgram_put_byte_callback(int b, mem_t *ctx) @@ -444,9 +444,9 @@ static int dgram_get_byte_callback(mem_t *ctx) if (nbytes == -1) { d->err = errno; - uw_throwf(socket_error_s, - lit("get-byte: recv on ~s failed: ~d/~s"), - d->stream, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, + lit("get-byte: recv on ~s failed: ~d/~s"), + d->stream, num(errno), errno_to_str(errno), nao); } uw_unwind { @@ -531,21 +531,21 @@ static val dgram_flush(val stream) if (nwrit != d->tx_pos) { d->err = (nwrit < 0) ? errno : ENOBUFS; - uw_throwf(socket_error_s, - lit("flush-stream: sendto on ~s ~a: ~d/~s"), - stream, - (nwrit < 0) ? lit("failed") : lit("truncated"), - num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, + lit("flush-stream: sendto on ~s ~a: ~d/~s"), + stream, + (nwrit < 0) ? lit("failed") : lit("truncated"), + num(errno), errno_to_str(errno), nao); } free(d->tx_buf); d->tx_buf = 0; d->tx_pos = 0; } else { - d->err = ENOTCONN; - uw_throwf(socket_error_s, - lit("flush-stream: cannot transmit on ~s: peer not set"), - stream, nao); + errno = d->err = ENOTCONN; + uw_ethrowf(socket_error_s, + lit("flush-stream: cannot transmit on ~s: peer not set"), + stream, nao); } } return t; @@ -712,8 +712,8 @@ static val sock_bind(val sock, val sockaddr) sockaddr_pack(sockaddr, family, &sa, &salen, self); if (bind(fd, coerce(struct sockaddr *, &sa), salen) != 0) - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); stream_set_prop(sock, addr_k, sockaddr); return t; @@ -807,8 +807,8 @@ static int to_connect(int fd, struct sockaddr *addr, socklen_t len, case -1: return -1; case 0: - uw_throwf(timeout_error_s, lit("~a: ~s: timeout on ~s"), - self, sock, sockaddr, nao); + uw_ethrowf(timeout_error_s, lit("~a: ~s: timeout on ~s"), + self, sock, sockaddr, nao); default: return 0; } @@ -842,8 +842,8 @@ static val open_sockfd(val fd, val family, val type, val mode_str, val self) if (!f) { int eno = errno; close(c_num(fd, self)); - uw_throwf(errno_to_file_error(eno), lit("error creating stream for socket ~a: ~d/~s"), - fd, num(eno), errno_to_str(eno), nao); + uw_ethrowf(errno_to_file_error(eno), lit("error creating stream for socket ~a: ~d/~s"), + fd, num(eno), errno_to_str(eno), nao); } return set_mode_props(m, make_sock_stream(f, family, type)); @@ -864,8 +864,8 @@ static val sock_connect(val sock, val sockaddr, val timeout) if (to_connect(c_num(sfd, self), coerce(struct sockaddr *, &sa), salen, sock, sockaddr, default_null_arg(timeout), self) != 0) - uw_throwf(socket_error_s, lit("~a: ~s to addr ~s: ~d/~s"), - self, sock, sockaddr, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a: ~s to addr ~s: ~d/~s"), + self, sock, sockaddr, num(errno), errno_to_str(errno), nao); sock_set_peer(sock, sockaddr); @@ -925,8 +925,8 @@ static val sock_listen(val sock, val backlog) return t; failed: - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); } static val sock_accept(val sock, val mode_str, val timeout_in) @@ -952,7 +952,7 @@ static val sock_accept(val sock, val mode_str, val timeout_in) case -1: goto badfd; case 0: - uw_throwf(timeout_error_s, lit("~a: ~s: timeout"), self, sock, nao); + uw_ethrowf(timeout_error_s, lit("~a: ~s: timeout"), self, sock, nao); default: break; } @@ -1038,11 +1038,11 @@ static val sock_accept(val sock, val mode_str, val timeout_in) } } failed: - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), self, num(errno), errno_to_str(errno), nao); badfd: - uw_throwf(socket_error_s, lit("~a: cannot accept on ~s"), - self, sock, nao); + uw_ethrowf(socket_error_s, lit("~a: cannot accept on ~s"), + self, sock, nao); } static val sock_shutdown(val sock, val how) @@ -1053,8 +1053,8 @@ static val sock_shutdown(val sock, val how) flush_stream(sock); if (shutdown(c_num(sfd, self), c_num(default_arg(how, num_fast(SHUT_WR)), self))) - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); return t; } @@ -1070,9 +1070,9 @@ static val sock_timeout(val sock, val usec, val name, int which, val self) tv.tv_usec = u % 1000000; if (setsockopt(fd, SOL_SOCKET, which, &tv, sizeof tv) != 0) - uw_throwf(socket_error_s, lit("~a failed on ~s: ~d/~s"), - name, sock, num(errno), - errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed on ~s: ~d/~s"), + name, sock, num(errno), + errno_to_str(errno), nao); return sock; } @@ -1118,8 +1118,8 @@ static val socketpair_wrap(val family, val type, val mode_str) uw_simple_catch_begin; if (res < 0) - uw_throwf(socket_error_s, lit("~a failed: ~d/~s"), - self, num(errno), errno_to_str(errno), nao); + uw_ethrowf(socket_error_s, lit("~a failed: ~d/~s"), + self, num(errno), errno_to_str(errno), nao); #if SOCK_NONBLOCK || SOCK_CLOEXEC type = num_fast(c_num(type, self) & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)); |