Compare commits

...

8 Commits

Author SHA1 Message Date
Meghan Denny
72031eeafc Merge remote-tracking branch 'origin/main' into nektro-patch-34511 2025-09-05 21:04:03 -07:00
Meghan Denny
05f102ee58 fix test-http-no-content-length 2025-09-05 21:02:43 -07:00
Meghan Denny
609b575500 bump 2025-09-05 20:58:23 -07:00
Meghan Denny
1a0e3b22a8 fix socket.test.ts 2025-09-05 17:36:26 -07:00
Meghan Denny
32c8e541d6 fix fetch.unix.test.ts 2025-09-05 17:36:13 -07:00
Meghan Denny
f312e9ad30 fix posix release build 2025-09-05 16:46:36 -07:00
autofix-ci[bot]
d923684b4a [autofix.ci] apply automated fixes 2025-09-05 22:40:15 +00:00
Meghan Denny
eed648e28f node:net: improve SytemError errno consistency 2025-09-05 15:36:25 -07:00
43 changed files with 728 additions and 193 deletions

View File

@@ -600,7 +600,7 @@ function getTestBunStep(platform, options, testOptions = {}) {
retry: getRetry(),
cancel_on_build_failing: isMergeQueue(),
parallelism: unifiedTests ? undefined : os === "darwin" ? 2 : 10,
timeout_in_minutes: profile === "asan" || os === "windows" ? 45 : 30,
timeout_in_minutes: 60,
command:
os === "windows"
? `node .\\scripts\\runner.node.mjs ${args.join(" ")}`

View File

@@ -584,7 +584,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol, in
if (UNLIKELY(created_fd == -1)) {
if (err != NULL) {
*err = errno;
*err = LIBUS_ERR;
}
return LIBUS_SOCKET_ERROR;
}
@@ -597,7 +597,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol, in
if (UNLIKELY(created_fd == -1)) {
if (err != NULL) {
*err = errno;
*err = LIBUS_ERR;
}
return LIBUS_SOCKET_ERROR;
}
@@ -742,7 +742,7 @@ ssize_t bsd_recvmsg(LIBUS_SOCKET_DESCRIPTOR fd, struct msghdr *msg, int flags) {
#if !defined(_WIN32)
#include <sys/uio.h>
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length, int *error) {
struct iovec chunks[2];
chunks[0].iov_base = (char *)header;
@@ -756,15 +756,18 @@ ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_le
if (UNLIKELY(IS_EINTR(written))) {
continue;
}
if (written < 0) {
if (error != NULL) *error = LIBUS_ERR;
}
return written;
}
}
#else
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length) {
ssize_t written = bsd_send(fd, header, header_length);
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length, int *error) {
ssize_t written = bsd_send(fd, header, header_length, error);
if (written == header_length) {
ssize_t second_write = bsd_send(fd, payload, payload_length);
ssize_t second_write = bsd_send(fd, payload, payload_length, error);
if (second_write > 0) {
written += second_write;
}
@@ -773,7 +776,7 @@ ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_le
}
#endif
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length) {
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int *error) {
while (1) {
// MSG_MORE (Linux), MSG_PARTIAL (Windows), TCP_NOPUSH (BSD)
@@ -787,6 +790,10 @@ ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length) {
if (UNLIKELY(IS_EINTR(rc))) {
continue;
}
if (rc < 0) {
if (error != NULL) *error = LIBUS_ERR;
return -1;
}
return rc;
}
@@ -819,16 +826,18 @@ static int us_internal_bind_and_listen(LIBUS_SOCKET_DESCRIPTOR listenFd, struct
do
result = bind(listenFd, listenAddr, listenAddrLength);
while (IS_EINTR(result));
if (result == -1) {
*error = LIBUS_ERR;
if (error != NULL) *error = LIBUS_ERR;
return -1;
}
do
result = listen(listenFd, backlog);
while (IS_EINTR(result));
*error = LIBUS_ERR;
if (result == -1) {
if (error != NULL) *error = LIBUS_ERR;
return -1;
}
return result;
}
@@ -951,7 +960,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int
struct addrinfo *listenAddr;
for (struct addrinfo *a = result; a != NULL; a = a->ai_next) {
if (a->ai_family == AF_INET6) {
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, NULL);
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, error);
if (listenFd == LIBUS_SOCKET_ERROR) {
continue;
}
@@ -968,7 +977,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int
for (struct addrinfo *a = result; a != NULL; a = a->ai_next) {
if (a->ai_family == AF_INET) {
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, NULL);
listenFd = bsd_create_socket(a->ai_family, a->ai_socktype, a->ai_protocol, error);
if (listenFd == LIBUS_SOCKET_ERROR) {
continue;
}
@@ -996,7 +1005,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int
#include <sys/stat.h>
#include <stddef.h>
static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path, size_t path_len, int* dirfd_linux_workaround_for_unix_path_len, struct sockaddr_un *server_address, size_t* addrlen) {
static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path, size_t path_len, int* dirfd_linux_workaround_for_unix_path_len, struct sockaddr_un *server_address, size_t* addrlen, int *error) {
memset(server_address, 0, sizeof(struct sockaddr_un));
server_address->sun_family = AF_UNIX;
@@ -1005,7 +1014,7 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
// simulate ENOENT
SetLastError(ERROR_PATH_NOT_FOUND);
#else
errno = ENOENT;
*error = ENOENT;
#endif
return LIBUS_SOCKET_ERROR;
}
@@ -1024,13 +1033,13 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
// if the path is just a single character, or the path is too long, we cannot use this method
if (dirname_len < 2 || (path_len - dirname_len + 1) >= sizeof(server_address->sun_path)) {
errno = ENAMETOOLONG;
if (error != NULL) *error = EINVAL;
return LIBUS_SOCKET_ERROR;
}
char dirname_buf[4096];
if (dirname_len + 1 > sizeof(dirname_buf)) {
errno = ENAMETOOLONG;
if (error != NULL) *error = EINVAL;
return LIBUS_SOCKET_ERROR;
}
@@ -1039,14 +1048,14 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
int socket_dir_fd = open(dirname_buf, O_CLOEXEC | O_PATH | O_DIRECTORY, 0700);
if (socket_dir_fd == -1) {
errno = ENAMETOOLONG;
if (error != NULL) *error = EINVAL;
return LIBUS_SOCKET_ERROR;
}
int sun_path_len = snprintf(server_address->sun_path, sizeof(server_address->sun_path), "/proc/self/fd/%d/%s", socket_dir_fd, path + dirname_len);
if (sun_path_len >= sizeof(server_address->sun_path) || sun_path_len < 0) {
close(socket_dir_fd);
errno = ENAMETOOLONG;
if (error != NULL) *error = EINVAL;
return LIBUS_SOCKET_ERROR;
}
@@ -1069,7 +1078,10 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
// simulate ENAMETOOLONG
SetLastError(ERROR_FILENAME_EXCED_RANGE);
#else
errno = ENAMETOOLONG;
// was ENAMETOOLONG but changed to EINVAL to align with node's UV_PIPE_NO_TRUNCATE flag
// https://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_bind2
// https://github.com/nodejs/node/blob/v24.0.0/src/pipe_wrap.cc#L168
*error = EINVAL;
#endif
return LIBUS_SOCKET_ERROR;
@@ -1082,7 +1094,7 @@ static LIBUS_SOCKET_DESCRIPTOR bsd_create_unix_socket_address(const char *path,
static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_listen_socket_unix(const char* path, int options, struct sockaddr_un* server_address, size_t addrlen, int* error) {
LIBUS_SOCKET_DESCRIPTOR listenFd = LIBUS_SOCKET_ERROR;
listenFd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, NULL);
listenFd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, error);
if (listenFd == LIBUS_SOCKET_ERROR) {
return LIBUS_SOCKET_ERROR;
@@ -1114,7 +1126,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket_unix(const char *path, size_t l
int dirfd_linux_workaround_for_unix_path_len = -1;
struct sockaddr_un server_address;
size_t addrlen = 0;
if (bsd_create_unix_socket_address(path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen)) {
if (bsd_create_unix_socket_address(path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen, error)) {
return LIBUS_SOCKET_ERROR;
}
@@ -1225,11 +1237,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port, int op
/* We bind here as well */
if (bind(listenFd, listenAddr->ai_addr, (socklen_t) listenAddr->ai_addrlen)) {
if (err != NULL) {
#ifdef _WIN32
*err = WSAGetLastError();
#else
*err = errno;
#endif
*err = LIBUS_ERR;
}
bsd_close_socket(listenFd);
freeaddrinfo(result);
@@ -1328,7 +1336,7 @@ int bsd_disconnect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd) {
// return 0; // no ecn defaults to 0
// }
static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr, size_t namelen)
static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr, size_t namelen, int *error)
{
#ifdef _WIN32
while (1) {
@@ -1347,6 +1355,7 @@ static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr,
continue;
}
default: {
if (error != NULL) *error = us_wsa_to_libuv_errno(err);
return err;
}
}
@@ -1367,7 +1376,8 @@ static int bsd_do_connect_raw(LIBUS_SOCKET_DESCRIPTOR fd, struct sockaddr *addr,
return 0;
}
return errno;
if (error != NULL) *error = LIBUS_ERR;
return r;
}
return 0;
@@ -1409,8 +1419,8 @@ static int is_loopback(struct sockaddr_storage *sockaddr) {
}
#endif
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options) {
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(addr->ss_family, SOCK_STREAM, 0, NULL);
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options, int *error) {
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(addr->ss_family, SOCK_STREAM, 0, error);
if (fd == LIBUS_SOCKET_ERROR) {
return LIBUS_SOCKET_ERROR;
}
@@ -1447,7 +1457,7 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr,
}
#endif
int rc = bsd_do_connect_raw(fd, (struct sockaddr*) addr, addr->ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
int rc = bsd_do_connect_raw(fd, (struct sockaddr*) addr, addr->ss_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), error);
if (rc != 0) {
bsd_close_socket(fd);
@@ -1456,8 +1466,8 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr,
return fd;
}
static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const char *server_path, size_t len, int options, struct sockaddr_un* server_address, const size_t addrlen) {
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, NULL);
static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const char *server_path, size_t len, int options, struct sockaddr_un* server_address, const size_t addrlen, int *error) {
LIBUS_SOCKET_DESCRIPTOR fd = bsd_create_socket(AF_UNIX, SOCK_STREAM, 0, error);
if (fd == LIBUS_SOCKET_ERROR) {
return LIBUS_SOCKET_ERROR;
@@ -1465,7 +1475,7 @@ static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const cha
win32_set_nonblocking(fd);
if (bsd_do_connect_raw(fd, (struct sockaddr *)server_address, addrlen) != 0) {
if (bsd_do_connect_raw(fd, (struct sockaddr *)server_address, addrlen, error) != 0) {
bsd_close_socket(fd);
return LIBUS_SOCKET_ERROR;
}
@@ -1473,15 +1483,15 @@ static LIBUS_SOCKET_DESCRIPTOR internal_bsd_create_connect_socket_unix(const cha
return fd;
}
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t len, int options) {
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t len, int options, int *error) {
struct sockaddr_un server_address;
size_t addrlen = 0;
int dirfd_linux_workaround_for_unix_path_len = -1;
if (bsd_create_unix_socket_address(server_path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen)) {
if (bsd_create_unix_socket_address(server_path, len, &dirfd_linux_workaround_for_unix_path_len, &server_address, &addrlen, error)) {
return LIBUS_SOCKET_ERROR;
}
LIBUS_SOCKET_DESCRIPTOR fd = internal_bsd_create_connect_socket_unix(server_path, len, options, &server_address, addrlen);
LIBUS_SOCKET_DESCRIPTOR fd = internal_bsd_create_connect_socket_unix(server_path, len, options, &server_address, addrlen, error);
#if defined(__linux__)
if (dirfd_linux_workaround_for_unix_path_len != -1) {

View File

@@ -430,8 +430,8 @@ struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_sock
return ls;
}
struct us_socket_t* us_socket_context_connect_resolved_dns(struct us_socket_context_t *context, struct sockaddr_storage* addr, int options, int socket_ext_size) {
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(addr, options);
struct us_socket_t* us_socket_context_connect_resolved_dns(struct us_socket_context_t *context, struct sockaddr_storage* addr, int options, int socket_ext_size, int *error) {
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(addr, options, error);
if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
return NULL;
}
@@ -501,10 +501,10 @@ static bool try_parse_ip(const char *ip_str, int port, struct sockaddr_storage *
return 0;
}
void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size, int* has_dns_resolved) {
void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size, int* has_dns_resolved, int *error) {
#ifndef LIBUS_NO_SSL
if (ssl == 1) {
return us_internal_ssl_socket_context_connect((struct us_internal_ssl_socket_context_t *) context, host, port, options, socket_ext_size, has_dns_resolved);
return us_internal_ssl_socket_context_connect((struct us_internal_ssl_socket_context_t *) context, host, port, options, socket_ext_size, has_dns_resolved, error);
}
#endif
@@ -514,7 +514,7 @@ void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, co
struct sockaddr_storage addr;
if (try_parse_ip(host, port, &addr)) {
*has_dns_resolved = 1;
return us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size);
return us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size, error);
}
struct addrinfo_request* ai_req;
@@ -534,7 +534,7 @@ void *us_socket_context_connect(int ssl, struct us_socket_context_t *context, co
struct sockaddr_storage addr;
init_addr_with_port(&entries->info, port, &addr);
*has_dns_resolved = 1;
struct us_socket_t *s = us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size);
struct us_socket_t *s = us_socket_context_connect_resolved_dns(context, &addr, options, socket_ext_size, error);
Bun__addrinfo_freeRequest(ai_req, s == NULL);
return s;
}
@@ -566,7 +566,7 @@ int start_connections(struct us_connecting_socket_t *c, int count) {
for (; c->addrinfo_head != NULL && opened < count; c->addrinfo_head = c->addrinfo_head->ai_next) {
struct sockaddr_storage addr;
init_addr_with_port(c->addrinfo_head, c->port, &addr);
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(&addr, c->options);
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(&addr, c->options, NULL);
if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
continue;
}
@@ -655,6 +655,8 @@ void us_internal_socket_after_open(struct us_socket_t *s, int error) {
break;
}
default: {
if (error == WSAENOTCONN) error = WSAECONNREFUSED;
error = us_wsa_to_libuv_errno(error);
break;
}
}
@@ -733,14 +735,14 @@ void us_internal_socket_after_open(struct us_socket_t *s, int error) {
}
}
struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_context_t *context, const char *server_path, size_t pathlen, int options, int socket_ext_size) {
struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_context_t *context, const char *server_path, size_t pathlen, int options, int socket_ext_size, int *error) {
#ifndef LIBUS_NO_SSL
if (ssl) {
return (struct us_socket_t *) us_internal_ssl_socket_context_connect_unix((struct us_internal_ssl_socket_context_t *) context, server_path, pathlen, options, socket_ext_size);
return (struct us_socket_t *) us_internal_ssl_socket_context_connect_unix((struct us_internal_ssl_socket_context_t *) context, server_path, pathlen, options, socket_ext_size, error);
}
#endif
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket_unix(server_path, pathlen, options);
LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket_unix(server_path, pathlen, options, error);
if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
return 0;
}

View File

@@ -135,7 +135,7 @@ int BIO_s_custom_write(BIO *bio, const char *data, int length) {
struct loop_ssl_data *loop_ssl_data =
(struct loop_ssl_data *)BIO_get_data(bio);
int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length);
int written = us_socket_write(0, loop_ssl_data->ssl_socket, data, length, NULL);
BIO_clear_retry_flags(bio);
if (!written) {
@@ -1608,11 +1608,11 @@ static void us_internal_zero_ssl_data_for_connected_socket_before_onopen(struct
// TODO does this need more changes?
struct us_socket_t *us_internal_ssl_socket_context_connect(
struct us_internal_ssl_socket_context_t *context, const char *host,
int port, int options, int socket_ext_size, int* is_connecting) {
int port, int options, int socket_ext_size, int* is_connecting, int *error) {
struct us_internal_ssl_socket_t *s = (struct us_internal_ssl_socket_t *)us_socket_context_connect(
2, &context->sc, host, port, options,
sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
socket_ext_size, is_connecting);
socket_ext_size, is_connecting, error);
if (*is_connecting && s) {
us_internal_zero_ssl_data_for_connected_socket_before_onopen(s);
}
@@ -1621,11 +1621,11 @@ struct us_socket_t *us_internal_ssl_socket_context_connect(
}
struct us_socket_t *us_internal_ssl_socket_context_connect_unix(
struct us_internal_ssl_socket_context_t *context, const char *server_path,
size_t pathlen, int options, int socket_ext_size) {
size_t pathlen, int options, int socket_ext_size, int *error) {
struct us_socket_t *s = (struct us_socket_t *)us_socket_context_connect_unix(
0, &context->sc, server_path, pathlen, options,
sizeof(struct us_internal_ssl_socket_t) - sizeof(struct us_socket_t) +
socket_ext_size);
socket_ext_size, error);
if (s) {
us_internal_zero_ssl_data_for_connected_socket_before_onopen((struct us_internal_ssl_socket_t*) s);
}
@@ -1746,7 +1746,7 @@ int us_internal_ssl_socket_raw_write(struct us_internal_ssl_socket_t *s,
if (us_socket_is_closed(0, &s->s) || us_internal_ssl_socket_is_shut_down(s)) {
return 0;
}
return us_socket_write(0, &s->s, data, length);
return us_socket_write(0, &s->s, data, length, NULL);
}
int us_internal_ssl_socket_write(struct us_internal_ssl_socket_t *s,

View File

@@ -63,8 +63,9 @@ void us_internal_loop_update_pending_ready_polls(struct us_loop_t *loop,
#endif
#ifdef _WIN32
int us_wsa_to_libuv_errno(int);
#define IS_EINTR(rc) (rc == SOCKET_ERROR && WSAGetLastError() == WSAEINTR)
#define LIBUS_ERR WSAGetLastError()
#define LIBUS_ERR us_wsa_to_libuv_errno(WSAGetLastError())
#else
#include <errno.h>
#define IS_EINTR(rc) (rc == -1 && errno == EINTR)
@@ -410,11 +411,12 @@ struct us_listen_socket_t *us_internal_ssl_socket_context_listen_unix(
struct us_socket_t *us_internal_ssl_socket_context_connect(
us_internal_ssl_socket_context_r context, const char *host,
int port, int options, int socket_ext_size, int* is_resolved);
int port, int options, int socket_ext_size, int* is_resolved,
int *error);
struct us_socket_t *us_internal_ssl_socket_context_connect_unix(
us_internal_ssl_socket_context_r context, const char *server_path,
size_t pathlen, int options, int socket_ext_size);
size_t pathlen, int options, int socket_ext_size, int *error);
int us_internal_ssl_socket_write(us_internal_ssl_socket_r s,
const char *data, int length);

View File

@@ -210,11 +210,11 @@ ssize_t bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
#if !defined(_WIN32)
ssize_t bsd_recvmsg(LIBUS_SOCKET_DESCRIPTOR fd, struct msghdr *msg, int flags);
#endif
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length);
ssize_t bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int *error);
#if !defined(_WIN32)
ssize_t bsd_sendmsg(LIBUS_SOCKET_DESCRIPTOR fd, const struct msghdr *msg, int flags);
#endif
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
ssize_t bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length, int *error);
int bsd_would_block();
// return LIBUS_SOCKET_ERROR or the fd that represents listen socket
@@ -228,9 +228,9 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port, int op
int bsd_connect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd, const char *host, int port);
int bsd_disconnect_udp_socket(LIBUS_SOCKET_DESCRIPTOR fd);
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options);
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(struct sockaddr_storage *addr, int options, int *error);
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t pathlen, int options);
LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, size_t pathlen, int options, int *error);
#ifndef MSG_DONTWAIT
#define MSG_DONTWAIT 0

View File

@@ -328,10 +328,10 @@ void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls) nonnull_fn_d
per the happy eyeballs algorithm
*/
void *us_socket_context_connect(int ssl, struct us_socket_context_t * nonnull_arg context,
const char *host, int port, int options, int socket_ext_size, int *is_connecting) __attribute__((nonnull(2)));
const char *host, int port, int options, int socket_ext_size, int *is_connecting, int *error) __attribute__((nonnull(2)));
struct us_socket_t *us_socket_context_connect_unix(int ssl, us_socket_context_r context,
const char *server_path, size_t pathlen, int options, int socket_ext_size) __attribute__((nonnull(2)));
const char *server_path, size_t pathlen, int options, int socket_ext_size, int *error) __attribute__((nonnull(2)));
/* Is this socket established? Can be used to check if a connecting socket has fired the on_open event yet.
* Can also be used to determine if a socket is a listen_socket or not, but you probably know that already. */
@@ -421,10 +421,10 @@ void *us_socket_get_native_handle(int ssl, us_socket_r s) nonnull_fn_decl;
/* Write up to length bytes of data. Returns actual bytes written.
* Will call the on_writable callback of active socket context on failure to write everything off in one go. */
int us_socket_write(int ssl, us_socket_r s, const char * nonnull_arg data, int length) nonnull_fn_decl;
int us_socket_write(int ssl, us_socket_r s, const char * nonnull_arg data, int length, int *error);
/* Special path for non-SSL sockets. Used to send header and payload in one go. Works like us_socket_write. */
int us_socket_write2(int ssl, us_socket_r s, const char *header, int header_length, const char *payload, int payload_length) nonnull_fn_decl;
int us_socket_write2(int ssl, us_socket_r s, const char * nonnull_arg header, int header_length, const char * nonnull_arg payload, int payload_length, int *error);
/* Set a low precision, high performance timer on a socket. A socket can only have one single active timer
* at any given point in time. Will remove any such pre set timer */

View File

@@ -307,7 +307,7 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in
/* Both connect and listen sockets are semi-sockets
* but they poll for different events */
if (us_poll_events(p) == LIBUS_SOCKET_WRITABLE) {
us_internal_socket_after_open((struct us_socket_t *) p, error || eof);
us_internal_socket_after_open((struct us_socket_t *) p, (error || eof) ? ECONNREFUSED : 0);
} else {
struct us_listen_socket_t *listen_socket = (struct us_listen_socket_t *) p;
struct bsd_addr_t addr;

View File

@@ -289,12 +289,12 @@ struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_e
}
/* This is not available for SSL sockets as it makes no sense. */
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length) {
int us_socket_write2(int ssl, struct us_socket_t *s, const char *header, int header_length, const char *payload, int payload_length, int *error) {
if (us_socket_is_closed(ssl, s) || us_socket_is_shut_down(ssl, s)) {
return 0;
}
int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length);
int written = bsd_write2(us_poll_fd(&s->p), header, header_length, payload, payload_length, error);
if (written != header_length + payload_length) {
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
}
@@ -357,7 +357,7 @@ void *us_connecting_socket_get_native_handle(int ssl, struct us_connecting_socke
return (void *) (uintptr_t) -1;
}
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length) {
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int *error) {
#ifndef LIBUS_NO_SSL
if (ssl) {
return us_internal_ssl_socket_write((struct us_internal_ssl_socket_t *) s, data, length);
@@ -367,7 +367,7 @@ int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length
return 0;
}
int written = bsd_send(us_poll_fd(&s->p), data, length);
int written = bsd_send(us_poll_fd(&s->p), data, length, error);
if (written != length) {
s->context->loop->data.last_write_failed = 1;
us_poll_change(&s->p, s->context->loop, LIBUS_SOCKET_READABLE | LIBUS_SOCKET_WRITABLE);
@@ -502,7 +502,7 @@ int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int le
}
#endif
// non-TLS is always raw
return us_socket_write(ssl, s, data, length);
return us_socket_write(ssl, s, data, length, NULL);
}
unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const char **dest, int *port, int *is_ipv6)

View File

@@ -247,7 +247,7 @@ public:
int max_flush_len = std::min(buffer_len, (size_t)INT_MAX);
/* Attempt to write data to the socket */
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len);
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, NULL);
total_written += written;
/* Check if we couldn't write the entire buffer */
@@ -297,7 +297,7 @@ public:
int max_flush_len = std::min(buffer_len, (size_t)INT_MAX);
/* Write off as much as we can */
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len);
int written = us_socket_write(SSL, (us_socket_t *) this, asyncSocketData->buffer.data(), max_flush_len, NULL);
/* On failure return, otherwise continue down the function */
if ((unsigned int) written < buffer_len) {
/* Update buffering (todo: we can do better here if we keep track of what happens to this guy later on) */
@@ -342,7 +342,7 @@ public:
}
} else {
/* We are not corked */
int written = us_socket_write(SSL, (us_socket_t *) this, src, length);
int written = us_socket_write(SSL, (us_socket_t *) this, src, length, NULL);
/* Did we fail? */
if (written < length) {
@@ -402,4 +402,4 @@ public:
}
#endif // UWS_ASYNCSOCKET_H
#endif // UWS_ASYNCSOCKET_H

View File

@@ -380,7 +380,7 @@ private:
httpContextData->onClientError(SSL, s, result.parserError, data, length);
}
/* For errors, we only deliver them "at most once". We don't care if they get halfways delivered or not. */
us_socket_write(SSL, s, httpErrorResponses[httpErrorStatusCode].data(), (int) httpErrorResponses[httpErrorStatusCode].length());
us_socket_write(SSL, s, httpErrorResponses[httpErrorStatusCode].data(), (int) httpErrorResponses[httpErrorStatusCode].length(), NULL);
us_socket_shutdown(SSL, s);
/* Close any socket on HTTP errors */
us_socket_close(SSL, s, 0, nullptr);

View File

@@ -114,7 +114,7 @@ public:
if (message.length() >= 16 * 1024 && !compress && !SSL && !webSocketData->subscriber && getBufferedAmount() == 0 && Super::getLoopData()->getCorkOffset() == 0) {
char header[10];
int header_length = (int) protocol::formatMessage<isServer>(header, "", 0, opCode, message.length(), compress, fin);
int written = us_socket_write2(0, (struct us_socket_t *)this, header, header_length, message.data(), (int) message.length());
int written = us_socket_write2(0, (struct us_socket_t *)this, header, header_length, message.data(), (int) message.length(), NULL);
if (written != header_length + (int) message.length()) {
/* Buffer up backpressure */
@@ -380,4 +380,4 @@ public:
}
#endif // UWS_WEBSOCKET_H
#endif // UWS_WEBSOCKET_H

View File

@@ -2395,7 +2395,7 @@ pub const Resolver = struct {
.result => |result| return result,
.err => |err| {
const system_error = jsc.SystemError{
.errno = -1,
.errno = @intFromEnum(bun.sys.SystemErrno.EPERM),
.code = bun.String.static(err.code()),
.message = bun.String.static(err.label()),
};
@@ -3101,7 +3101,7 @@ pub const Resolver = struct {
defer syscall.deref();
const system_error = jsc.SystemError{
.errno = -1,
.errno = @intFromEnum(bun.sys.SystemErrno.EPERM),
.code = bun.String.static(err.code()),
.message = bun.String.static(err.label()),
.syscall = syscall,

View File

@@ -1523,7 +1523,10 @@ pub const H2FrameParser = struct {
pub fn _genericFlush(this: *H2FrameParser, comptime T: type, socket: T) usize {
const buffer = this.writeBuffer.slice()[this.writeBufferOffset..];
if (buffer.len > 0) {
const result: i32 = socket.writeMaybeCorked(buffer);
const result: i32 = switch (socket.writeMaybeCorked(buffer)) {
.result => |result| result,
.err => 0,
};
const written: u32 = if (result < 0) 0 else @intCast(result);
if (written < buffer.len) {
@@ -1554,7 +1557,10 @@ pub const H2FrameParser = struct {
const buffer = this.writeBuffer.slice()[this.writeBufferOffset..];
if (buffer.len > 0) {
{
const result: i32 = socket.writeMaybeCorked(buffer);
const result: i32 = switch (socket.writeMaybeCorked(buffer)) {
.result => |result| result,
.err => 0,
};
const written: u32 = if (result < 0) 0 else @intCast(result);
if (written < buffer.len) {
this.writeBufferOffset += written;
@@ -1571,7 +1577,10 @@ pub const H2FrameParser = struct {
this.writeBufferOffset = 0;
this.writeBuffer.len = 0;
{
const result: i32 = socket.writeMaybeCorked(bytes);
const result: i32 = switch (socket.writeMaybeCorked(bytes)) {
.result => |result| result,
.err => 0,
};
const written: u32 = if (result < 0) 0 else @intCast(result);
if (written < bytes.len) {
const pending = bytes[written..];
@@ -1591,7 +1600,10 @@ pub const H2FrameParser = struct {
}
return true;
}
const result: i32 = socket.writeMaybeCorked(bytes);
const result: i32 = switch (socket.writeMaybeCorked(bytes)) {
.result => |result| result,
.err => 0,
};
const written: u32 = if (result < 0) 0 else @intCast(result);
if (written < bytes.len) {
const pending = bytes[written..];

View File

@@ -108,7 +108,7 @@ pub fn NewSocket(comptime ssl: bool) type {
}
}
pub fn doConnect(this: *This, connection: Listener.UnixOrHost) !void {
pub fn doConnect(this: *This, connection: Listener.UnixOrHost, error_: ?*i32) !void {
bun.assert(this.socket_context != null);
this.ref();
errdefer this.deref();
@@ -121,6 +121,7 @@ pub fn NewSocket(comptime ssl: bool) type {
this.socket_context.?,
this,
this.flags.allow_half_open,
error_,
);
},
.unix => |u| {
@@ -129,10 +130,14 @@ pub fn NewSocket(comptime ssl: bool) type {
this.socket_context.?,
this,
this.flags.allow_half_open,
error_,
);
},
.fd => |f| {
const socket = This.Socket.fromFd(this.socket_context.?, f, This, this, null, false) orelse return error.ConnectionFailed;
const socket = This.Socket.fromFd(this.socket_context.?, f, This, this, null, false) orelse {
if (error_) |err| err.* = bun.sys.SystemErrno.ENOENT.to_uv_errno();
return error.ConnectionFailed;
};
this.onOpen(socket);
},
}
@@ -235,7 +240,7 @@ pub fn NewSocket(comptime ssl: bool) type {
}
this.ref();
defer this.deref();
this.internalFlush();
this.internalFlush(false) catch return;
log("onWritable buffered_data_for_node_net {d}", .{this.buffered_data_for_node_net.len});
// is not writable if we have buffered data or if we are already detached
if (this.buffered_data_for_node_net.len > 0 or this.socket.isDetached()) return;
@@ -299,15 +304,13 @@ pub fn NewSocket(comptime ssl: bool) type {
}
bun.assert(errno >= 0);
var errno_: c_int = if (errno == @intFromEnum(bun.sys.SystemErrno.ENOENT)) @intFromEnum(bun.sys.SystemErrno.ENOENT) else @intFromEnum(bun.sys.SystemErrno.ECONNREFUSED);
const code_ = if (errno == @intFromEnum(bun.sys.SystemErrno.ENOENT)) bun.String.static("ENOENT") else bun.String.static("ECONNREFUSED");
if (Environment.isWindows and errno_ == @intFromEnum(bun.sys.SystemErrno.ENOENT)) errno_ = @intFromEnum(bun.sys.SystemErrno.UV_ENOENT);
if (Environment.isWindows and errno_ == @intFromEnum(bun.sys.SystemErrno.ECONNREFUSED)) errno_ = @intFromEnum(bun.sys.SystemErrno.UV_ECONNREFUSED);
const errno_: c_uint = @intCast(errno);
const code_ = bun.String.static(@tagName(@as(bun.sys.SystemErrno, @enumFromInt(errno))));
const callback = handlers.onConnectError;
const globalObject = handlers.globalObject;
const err = jsc.SystemError{
.errno = -errno_,
.errno = errno_,
.message = bun.String.static("Failed to connect"),
.syscall = bun.String.static("connect"),
.code = code_,
@@ -857,9 +860,9 @@ pub fn NewSocket(comptime ssl: bool) type {
return JSValue.jsNumber(this.socket.remotePort());
}
pub fn writeMaybeCorked(this: *This, buffer: []const u8) i32 {
pub fn writeMaybeCorked(this: *This, buffer: []const u8) bun.Maybe(i32, bun.sys.Error) {
if (this.socket.isShutdown() or this.socket.isClosed()) {
return -1;
return .initResult(-1);
}
// we don't cork yet but we might later
@@ -870,15 +873,21 @@ pub fn NewSocket(comptime ssl: bool) type {
const uwrote: usize = @intCast(@max(res, 0));
this.bytes_written += uwrote;
log("write({d}) = {d}", .{ buffer.len, res });
return res;
return .initResult(res);
}
}
const res = this.socket.write(buffer);
const res = switch (this.socket.writeMaybe(buffer)) {
.result => |result| result,
.err => |err| {
if (err.errno == bun.sys.SystemErrno.EPIPE.to_uv_errno()) this.closeAndDetach(.normal);
return .initErr(err);
},
};
const uwrote: usize = @intCast(@max(res, 0));
this.bytes_written += uwrote;
log("write({d}) = {d}", .{ buffer.len, res });
return res;
return .initResult(res);
}
pub fn writeBuffered(this: *This, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
@@ -894,9 +903,9 @@ pub fn NewSocket(comptime ssl: bool) type {
return globalObject.throwValue(err.toErrorInstance(globalObject));
}
const args = callframe.argumentsUndef(2);
const args = callframe.argumentsAsArray(2);
return switch (this.writeOrEndBuffered(globalObject, args.ptr[0], args.ptr[1], false)) {
return switch (this.writeOrEndBuffered(globalObject, args[0], args[1], false)) {
.fail => .zero,
.success => |result| if (@max(result.wrote, 0) == result.total) .true else .false,
};
@@ -915,7 +924,7 @@ pub fn NewSocket(comptime ssl: bool) type {
.fail => .zero,
.success => |result| brk: {
if (result.wrote == result.total) {
this.internalFlush();
this.internalFlush(true) catch return .false;
}
break :brk JSValue.jsBoolean(@as(usize, @max(result.wrote, 0)) == result.total);
@@ -983,7 +992,7 @@ pub fn NewSocket(comptime ssl: bool) type {
if (comptime !ssl and Environment.isPosix) {
// fast-ish path: use writev() to avoid cloning to another buffer.
if (this.socket.socket == .connected and buffer.slice().len > 0) {
const rc = this.socket.socket.connected.write2(ssl, this.buffered_data_for_node_net.slice(), buffer.slice());
const rc = this.socket.socket.connected.write2(ssl, this.buffered_data_for_node_net.slice(), buffer.slice(), null);
const written: usize = @intCast(@max(rc, 0));
const leftover = total_to_write -| written;
if (leftover == 0) {
@@ -1013,7 +1022,10 @@ pub fn NewSocket(comptime ssl: bool) type {
// slower-path: clone the data, do one write.
bun.handleOom(this.buffered_data_for_node_net.append(bun.default_allocator, buffer.slice()));
const rc = this.writeMaybeCorked(this.buffered_data_for_node_net.slice());
const rc = switch (this.writeMaybeCorked(this.buffered_data_for_node_net.slice())) {
.result => |result| result,
.err => 0,
};
if (rc > 0) {
const wrote: usize = @intCast(@max(rc, 0));
// did we write everything?
@@ -1161,7 +1173,10 @@ pub fn NewSocket(comptime ssl: bool) type {
return .{ .success = .{} };
}
log("writeOrEnd {d}", .{bytes.len});
const wrote = this.writeMaybeCorked(bytes);
const wrote = switch (this.writeMaybeCorked(bytes)) {
.result => |result| result,
.err => 0,
};
const uwrote: usize = @intCast(@max(wrote, 0));
if (buffer_unwritten_data) {
const remaining = bytes[uwrote..];
@@ -1193,19 +1208,27 @@ pub fn NewSocket(comptime ssl: bool) type {
return this.flags.is_active and this.flags.end_after_flush and !this.flags.empty_packet_pending and this.buffered_data_for_node_net.len == 0;
}
fn internalFlush(this: *This) void {
fn internalFlush(this: *This, is_end: bool) error{CalledOnError}!void {
if (this.buffered_data_for_node_net.len > 0) {
const written: usize = @intCast(@max(this.socket.write(this.buffered_data_for_node_net.slice()), 0));
this.bytes_written += written;
if (written > 0) {
if (this.buffered_data_for_node_net.len > written) {
const remaining = this.buffered_data_for_node_net.slice()[written..];
_ = bun.c.memmove(this.buffered_data_for_node_net.ptr, remaining.ptr, remaining.len);
this.buffered_data_for_node_net.len = @truncate(remaining.len);
} else {
this.buffered_data_for_node_net.deinitWithAllocator(bun.default_allocator);
this.buffered_data_for_node_net = .{};
}
switch (this.socket.writeMaybe(this.buffered_data_for_node_net.slice())) {
.result => |written_| {
const written: usize = @intCast(written_);
this.bytes_written += written;
if (this.buffered_data_for_node_net.len > written) {
const remaining = this.buffered_data_for_node_net.slice()[written..];
_ = bun.c.memmove(this.buffered_data_for_node_net.ptr, remaining.ptr, remaining.len);
this.buffered_data_for_node_net.len = @truncate(remaining.len);
} else {
this.buffered_data_for_node_net.deinitWithAllocator(bun.default_allocator);
this.buffered_data_for_node_net = .{};
}
},
.err => |err| {
if (!is_end) {
this.handleError(err.toSystemError().toErrorInstance(this.handlers.?.globalObject));
return error.CalledOnError;
}
},
}
}
@@ -1219,7 +1242,7 @@ pub fn NewSocket(comptime ssl: bool) type {
pub fn flush(this: *This, _: *jsc.JSGlobalObject, _: *jsc.CallFrame) bun.JSError!JSValue {
jsc.markBinding(@src());
this.internalFlush();
this.internalFlush(false) catch return .js_undefined;
return .js_undefined;
}
@@ -1267,7 +1290,7 @@ pub fn NewSocket(comptime ssl: bool) type {
.fail => .zero,
.success => |result| brk: {
if (result.wrote == result.total) {
this.internalFlush();
this.internalFlush(true) catch return .jsNumber(0);
}
break :brk JSValue.jsNumber(result.wrote);
},
@@ -1850,7 +1873,7 @@ pub const DuplexUpgradeContext = struct {
}
} else {
if (this.tls) |tls| {
tls.handleConnectError(@intFromEnum(bun.sys.SystemErrno.ECONNREFUSED));
tls.handleConnectError(bun.sys.SystemErrno.ECONNREFUSED.to_uv_errno());
}
}
}
@@ -1883,7 +1906,7 @@ pub const DuplexUpgradeContext = struct {
bun.outOfMemory();
},
else => {
const errno = @intFromEnum(bun.sys.SystemErrno.ECONNREFUSED);
const errno = bun.sys.SystemErrno.ECONNREFUSED.to_uv_errno();
if (this.tls) |tls| {
const socket = TLSSocket.Socket.fromDuplex(&this.upgrade);

View File

@@ -772,8 +772,11 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
socket.ref();
SocketType.js.dataSetCached(socket.getThisValue(globalObject), globalObject, default_data);
socket.flags.allow_half_open = socket_config.allowHalfOpen;
socket.doConnect(connection) catch {
socket.handleConnectError(@intFromEnum(if (port == null) bun.sys.SystemErrno.ENOENT else bun.sys.SystemErrno.ECONNREFUSED));
var error_: i32 = 0;
socket.doConnect(connection, &error_) catch {
bun.assert(error_ > 0);
if (Environment.isWindows and port == null and error_ == bun.sys.SystemErrno.ECONNREFUSED.to_uv_errno()) error_ = bun.sys.SystemErrno.ENOENT.to_uv_errno(); //TODO: use better WSA api
socket.handleConnectError(error_);
return promise_value;
};

View File

@@ -1392,7 +1392,7 @@ pub fn spawnMaybeSync(
else
"";
var systemerror = bun.sys.Error.fromCode(if (err == error.EMFILE) .MFILE else .NFILE, .posix_spawn).withPath(display_path).toSystemError();
systemerror.errno = if (err == error.EMFILE) -bun.sys.UV_E.MFILE else -bun.sys.UV_E.NFILE;
systemerror.errno = if (err == error.EMFILE) bun.sys.UV_E.MFILE else bun.sys.UV_E.NFILE;
return globalThis.throwValue(systemerror.toErrorInstance(globalThis));
},
else => {
@@ -1410,7 +1410,7 @@ pub fn spawnMaybeSync(
"";
if (display_path.len > 0) {
var systemerror = err.withPath(display_path).toSystemError();
if (errno == .NOENT) systemerror.errno = -bun.sys.UV_E.NOENT;
if (errno == .NOENT) systemerror.errno = bun.sys.UV_E.NOENT;
return globalThis.throwValue(systemerror.toErrorInstance(globalThis));
}
},
@@ -1530,12 +1530,7 @@ pub fn spawnMaybeSync(
var posix_ipc_info: if (Environment.isPosix) IPC.Socket else void = undefined;
if (Environment.isPosix and !is_sync) {
if (maybe_ipc_mode) |mode| {
if (uws.us_socket_t.fromFd(
jsc_vm.rareData().spawnIPCContext(jsc_vm),
@sizeOf(*IPC.SendQueue),
posix_ipc_fd.cast(),
1,
)) |socket| {
if (uws.us_socket_t.fromFd(jsc_vm.rareData().spawnIPCContext(jsc_vm), @sizeOf(*IPC.SendQueue), posix_ipc_fd.cast(), 1)) |socket| {
subprocess.ipc_data = .init(mode, .{ .subprocess = subprocess }, .uninitialized);
posix_ipc_info = IPC.Socket.from(socket);
}
@@ -1747,7 +1742,7 @@ fn throwCommandNotFound(globalThis: *jsc.JSGlobalObject, command: []const u8) bu
const err = jsc.SystemError{
.message = bun.handleOom(bun.String.createFormat("Executable not found in $PATH: \"{s}\"", .{command})),
.code = bun.String.static("ENOENT"),
.errno = -bun.sys.UV_E.NOENT,
.errno = bun.sys.UV_E.NOENT,
.path = bun.String.cloneUTF8(command),
};
return globalThis.throwValue(err.toErrorInstance(globalThis));

View File

@@ -319,9 +319,10 @@ pub const UDPSocket = struct {
this.closed = true;
defer this.deinit();
if (err != 0) {
const code = @tagName(bun.sys.SystemErrno.init(@as(c_int, @intCast(err))).?);
const err_ = bun.sys.SystemErrno.init(@as(c_int, @intCast(err))).?;
const code = @tagName(err_);
const sys_err = jsc.SystemError{
.errno = err,
.errno = @intFromEnum(err_),
.code = bun.String.static(code),
.message = bun.handleOom(bun.String.createFormat("bind {s} {s}", .{ code, config.hostname })),
};

View File

@@ -1,5 +1,5 @@
pub const SystemError = extern struct {
errno: c_int = 0,
errno: c_uint = 0,
/// label for errno
code: String = .empty,
message: String, // it is illegal to have an empty message
@@ -22,7 +22,7 @@ pub const SystemError = extern struct {
pub fn getErrno(this: *const SystemError) bun.sys.E {
// The inverse in bun.sys.Error.toSystemError()
return @enumFromInt(this.errno * -1);
return @enumFromInt(this.errno);
}
pub fn deref(this: *const SystemError) void {

View File

@@ -4,7 +4,7 @@ pub const ZigException = extern struct {
runtime_type: JSRuntimeType,
/// SystemError only
errno: c_int = 0,
errno: c_uint = 0,
/// SystemError only
syscall: String = String.empty,
/// SystemError only

View File

@@ -2214,7 +2214,7 @@ JSC::EncodedJSValue SystemError__toErrorInstance(const SystemError* arg0, JSC::J
result->putDirect(vm, names.hostnamePublicName(), hostname, JSC::PropertyAttribute::DontDelete | 0);
}
result->putDirect(vm, names.errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
result->putDirect(vm, names.errnoPublicName(), jsNumber(-static_cast<int>(err.errno_)), JSC::PropertyAttribute::DontDelete | 0);
ASSERT_NO_PENDING_EXCEPTION(globalObject);
return JSC::JSValue::encode(result);
@@ -2252,8 +2252,8 @@ JSC::EncodedJSValue SystemError__toErrorInstanceWithInfoObject(const SystemError
info->putDirect(vm, clientData->builtinNames().codePublicName(), jsString(vm, codeString), JSC::PropertyAttribute::DontDelete | 0);
info->putDirect(vm, vm.propertyNames->message, jsString(vm, messageString), JSC::PropertyAttribute::DontDelete | 0);
info->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
result->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(err.errno_), JSC::PropertyAttribute::DontDelete | 0);
info->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(-static_cast<int>(err.errno_)), JSC::PropertyAttribute::DontDelete | 0);
result->putDirect(vm, clientData->builtinNames().errnoPublicName(), jsNumber(-static_cast<int>(err.errno_)), JSC::PropertyAttribute::DontDelete | 0);
ASSERT_NO_PENDING_EXCEPTION(globalObject);
return JSC::JSValue::encode(result);

View File

@@ -130,7 +130,7 @@ typedef struct ErrorableResolvedSource {
} ErrorableResolvedSource;
typedef struct SystemError {
int errno_;
unsigned int errno_;
BunString code;
BunString message;
BunString path;
@@ -197,7 +197,7 @@ typedef struct ZigStackTrace {
typedef struct ZigException {
unsigned char type;
uint16_t runtime_type;
int errno_;
unsigned int errno_;
BunString syscall;
BunString system_code;
BunString path;

View File

@@ -291,8 +291,8 @@ pub fn getPriority(global: *jsc.JSGlobalObject, pid: i32) bun.JSError!i32 {
.message = bun.String.static("no such process"),
.code = bun.String.static("ESRCH"),
.errno = comptime switch (bun.Environment.os) {
else => -@as(c_int, @intFromEnum(std.posix.E.SRCH)),
.windows => libuv.UV_ESRCH,
else => @intFromEnum(std.posix.E.SRCH),
.windows => -libuv.UV_ESRCH,
},
.syscall = bun.String.static("uv_os_getpriority"),
};
@@ -642,11 +642,12 @@ fn networkInterfacesWindows(globalThis: *jsc.JSGlobalObject) bun.JSError!jsc.JSV
var count: c_int = undefined;
const err = libuv.uv_interface_addresses(&ifaces, &count);
if (err != 0) {
bun.assert(err < 0);
const sys_err = jsc.SystemError{
.message = bun.String.static("uv_interface_addresses failed"),
.code = bun.String.static("ERR_SYSTEM_ERROR"),
//.info = info,
.errno = err,
.errno = @intCast(-err),
.syscall = bun.String.static("uv_interface_addresses"),
};
return globalThis.throwValue(sys_err.toErrorInstance(globalThis));
@@ -814,8 +815,8 @@ pub fn setPriority1(global: *jsc.JSGlobalObject, pid: i32, priority: i32) !void
.message = bun.String.static("no such process"),
.code = bun.String.static("ESRCH"),
.errno = comptime switch (bun.Environment.os) {
else => -@as(c_int, @intFromEnum(std.posix.E.SRCH)),
.windows => libuv.UV_ESRCH,
else => @intFromEnum(std.posix.E.SRCH),
.windows => -libuv.UV_ESRCH,
},
.syscall = bun.String.static("uv_os_getpriority"),
};
@@ -826,8 +827,8 @@ pub fn setPriority1(global: *jsc.JSGlobalObject, pid: i32, priority: i32) !void
.message = bun.String.static("permission denied"),
.code = bun.String.static("EACCES"),
.errno = comptime switch (bun.Environment.os) {
else => -@as(c_int, @intFromEnum(std.posix.E.ACCES)),
.windows => libuv.UV_EACCES,
else => @intFromEnum(std.posix.E.ACCES),
.windows => -libuv.UV_EACCES,
},
.syscall = bun.String.static("uv_os_getpriority"),
};
@@ -838,8 +839,8 @@ pub fn setPriority1(global: *jsc.JSGlobalObject, pid: i32, priority: i32) !void
.message = bun.String.static("operation not permitted"),
.code = bun.String.static("EPERM"),
.errno = comptime switch (bun.Environment.os) {
else => -@as(c_int, @intFromEnum(std.posix.E.SRCH)),
.windows => libuv.UV_ESRCH,
else => @intFromEnum(std.posix.E.SRCH),
.windows => -libuv.UV_ESRCH,
},
.syscall = bun.String.static("uv_os_getpriority"),
};
@@ -886,19 +887,12 @@ pub fn totalmem() u64 {
}
pub fn uptime(global: *jsc.JSGlobalObject) bun.JSError!f64 {
_ = global;
switch (Environment.os) {
.windows => {
var uptime_value: f64 = undefined;
const err = libuv.uv_uptime(&uptime_value);
if (err != 0) {
const sys_err = jsc.SystemError{
.message = bun.String.static("failed to get system uptime"),
.code = bun.String.static("ERR_SYSTEM_ERROR"),
.errno = err,
.syscall = bun.String.static("uv_uptime"),
};
return global.throwValue(sys_err.toErrorInstance(global));
}
_ = libuv.uv_uptime(&uptime_value);
// uv_uptime cannot fail on windows
return uptime_value;
},
.mac => {

View File

@@ -1637,7 +1637,7 @@ pub const ARES_ECANCELLED = 24;
pub const ARES_ESERVICE = 25;
pub const ARES_ENOSERVER = 26;
pub const Error = enum(i32) {
pub const Error = enum(u16) {
ENODATA = ARES_ENODATA,
EFORMERR = ARES_EFORMERR,
ESERVFAIL = ARES_ESERVFAIL,

View File

@@ -196,12 +196,12 @@ pub const SocketContext = opaque {
return c.us_socket_context_adopt_socket(@intFromBool(ssl), this, s, ext_size);
}
pub fn connect(this: *SocketContext, ssl: bool, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32) ?*anyopaque {
return c.us_socket_context_connect(@intFromBool(ssl), this, host, port, options, socket_ext_size, has_dns_resolved);
pub fn connect(this: *SocketContext, ssl: bool, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32, error_: ?*i32) ?*anyopaque {
return c.us_socket_context_connect(@intFromBool(ssl), this, host, port, options, socket_ext_size, has_dns_resolved, error_);
}
pub fn connectUnix(this: *SocketContext, ssl: bool, path: [:0]const u8, options: i32, socket_ext_size: i32) ?*us_socket_t {
return c.us_socket_context_connect_unix(@intFromBool(ssl), this, path.ptr, path.len, options, socket_ext_size);
pub fn connectUnix(this: *SocketContext, ssl: bool, path: [:0]const u8, options: i32, socket_ext_size: i32, error_: ?*i32) ?*us_socket_t {
return c.us_socket_context_connect_unix(@intFromBool(ssl), this, path.ptr, path.len, options, socket_ext_size, error_);
}
pub fn free(this: *SocketContext, ssl: bool) void {
@@ -254,8 +254,8 @@ pub const c = struct {
pub extern fn us_create_child_socket_context(ssl: i32, context: ?*SocketContext, context_ext_size: i32) ?*SocketContext;
pub extern fn us_socket_context_adopt_socket(ssl: i32, context: *SocketContext, s: *us_socket_t, ext_size: i32) ?*us_socket_t;
pub extern fn us_socket_context_close(ssl: i32, ctx: *anyopaque) void;
pub extern fn us_socket_context_connect(ssl: i32, context: *SocketContext, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32) ?*anyopaque;
pub extern fn us_socket_context_connect_unix(ssl: i32, context: *SocketContext, path: [*:0]const u8, pathlen: usize, options: i32, socket_ext_size: i32) ?*us_socket_t;
pub extern fn us_socket_context_connect(ssl: i32, context: *SocketContext, host: [*:0]const u8, port: i32, options: i32, socket_ext_size: i32, has_dns_resolved: *i32, error_: ?*i32) ?*anyopaque;
pub extern fn us_socket_context_connect_unix(ssl: i32, context: *SocketContext, path: [*:0]const u8, pathlen: usize, options: i32, socket_ext_size: i32, error_: ?*i32) ?*us_socket_t;
pub extern fn us_socket_context_ext(ssl: i32, context: *SocketContext) ?*anyopaque;
pub extern fn us_socket_context_free(ssl: i32, context: *SocketContext) void;
pub extern fn us_socket_context_get_native_handle(ssl: i32, context: *SocketContext) ?*anyopaque;

View File

@@ -326,6 +326,15 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
};
}
pub fn writeMaybe(this: ThisSocket, data: []const u8) bun.Maybe(i32, bun.sys.Error) {
return switch (this.socket) {
.upgradedDuplex => |socket| .initResult(socket.encodeAndWrite(data)),
.pipe => |pipe| .initResult(if (comptime Environment.isWindows) pipe.encodeAndWrite(data) else 0),
.connected => |socket| socket.writeMaybe(is_ssl, data),
.connecting, .detached => .initResult(0),
};
}
pub fn writeFd(this: ThisSocket, data: []const u8, file_descriptor: bun.FileDescriptor) i32 {
return switch (this.socket) {
.upgradedDuplex, .pipe => this.write(data),
@@ -506,8 +515,9 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
ctx: *Context,
comptime socket_field_name: []const u8,
allowHalfOpen: bool,
error_: ?*i32,
) !*Context {
const this_socket = try connectAnon(host, port, socket_ctx, ctx, allowHalfOpen);
const this_socket = try connectAnon(host, port, socket_ctx, ctx, allowHalfOpen, error_);
@field(ctx, socket_field_name) = this_socket;
return ctx;
}
@@ -574,6 +584,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
socket_ctx: *SocketContext,
ctx: *anyopaque,
allowHalfOpen: bool,
error_: ?*i32,
) !ThisSocket {
debug("connect(unix:{s})", .{path});
var stack_fallback = std.heap.stackFallback(1024, bun.default_allocator);
@@ -581,7 +592,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
const path_ = bun.handleOom(allocator.dupeZ(u8, path));
defer allocator.free(path_);
const socket = socket_ctx.connectUnix(is_ssl, path_, if (allowHalfOpen) uws.LIBUS_SOCKET_ALLOW_HALF_OPEN else 0, 8) orelse
const socket = socket_ctx.connectUnix(is_ssl, path_, if (allowHalfOpen) uws.LIBUS_SOCKET_ALLOW_HALF_OPEN else 0, 8, error_) orelse
return error.FailedToOpenSocket;
const socket_ = ThisSocket{ .socket = .{ .connected = socket } };
@@ -597,6 +608,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
socket_ctx: *SocketContext,
ptr: *anyopaque,
allowHalfOpen: bool,
error_: ?*i32,
) !ThisSocket {
debug("connect({s}, {d})", .{ raw_host, port });
var stack_fallback = std.heap.stackFallback(1024, bun.default_allocator);
@@ -619,6 +631,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
if (allowHalfOpen) uws.LIBUS_SOCKET_ALLOW_HALF_OPEN else 0,
@sizeOf(*anyopaque),
&did_dns_resolve,
error_,
) orelse return error.FailedToOpenSocket;
const socket = if (did_dns_resolve == 1)
ThisSocket{

View File

@@ -127,11 +127,19 @@ pub const us_socket_t = opaque {
}
pub fn write(this: *us_socket_t, ssl: bool, data: []const u8) i32 {
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len));
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len), null);
debug("us_socket_write({d}, {d}) = {d}", .{ @intFromPtr(this), data.len, rc });
return rc;
}
pub fn writeMaybe(this: *us_socket_t, ssl: bool, data: []const u8) bun.Maybe(i32, bun.sys.Error) {
var error_: u32 = 0;
const rc = c.us_socket_write(@intFromBool(ssl), this, data.ptr, @intCast(data.len), &error_);
debug("us_socket_write({d}, {d}) = {d}", .{ @intFromPtr(this), data.len, rc });
if (error_ > 0) return .initErr(.fromCodeInt(error_, .write));
return .initResult(rc);
}
pub fn writeFd(this: *us_socket_t, data: []const u8, file_descriptor: bun.FD) i32 {
if (bun.Environment.isWindows) @compileError("TODO: implement writeFd on Windows");
const rc = c.us_socket_ipc_write_fd(this, data.ptr, @intCast(data.len), file_descriptor.native());
@@ -139,8 +147,8 @@ pub const us_socket_t = opaque {
return rc;
}
pub fn write2(this: *us_socket_t, ssl: bool, first: []const u8, second: []const u8) i32 {
const rc = c.us_socket_write2(@intFromBool(ssl), this, first.ptr, first.len, second.ptr, second.len);
pub fn write2(this: *us_socket_t, ssl: bool, first: []const u8, second: []const u8, error_: ?*u32) i32 {
const rc = c.us_socket_write2(@intFromBool(ssl), this, first.ptr, first.len, second.ptr, second.len, error_);
debug("us_socket_write2({d}, {d}, {d}) = {d}", .{ @intFromPtr(this), first.len, second.len, rc });
return rc;
}
@@ -198,9 +206,9 @@ pub const c = struct {
pub extern fn us_socket_ext(ssl: i32, s: ?*us_socket_t) ?*anyopaque; // nullish to be safe
pub extern fn us_socket_context(ssl: i32, s: ?*us_socket_t) ?*SocketContext;
pub extern fn us_socket_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32) i32;
pub extern fn us_socket_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32, error_: ?*u32) i32;
pub extern fn us_socket_ipc_write_fd(s: ?*us_socket_t, data: [*c]const u8, length: i32, fd: i32) i32;
pub extern fn us_socket_write2(ssl: i32, *us_socket_t, header: ?[*]const u8, len: usize, payload: ?[*]const u8, usize) i32;
pub extern fn us_socket_write2(ssl: i32, *us_socket_t, header: ?[*]const u8, usize, payload: ?[*]const u8, usize, error_: ?*u32) i32;
pub extern fn us_socket_raw_write(ssl: i32, s: ?*us_socket_t, data: [*c]const u8, length: i32) i32;
pub extern fn us_socket_flush(ssl: i32, s: ?*us_socket_t) void;
@@ -218,12 +226,7 @@ pub const c = struct {
pub extern fn us_socket_get_fd(s: ?*us_socket_t) uws.LIBUS_SOCKET_DESCRIPTOR;
pub extern fn us_socket_verify_error(ssl: i32, context: *us_socket_t) uws.us_bun_verify_error_t;
pub extern fn us_socket_upgrade_to_tls(s: *us_socket_t, new_context: *SocketContext, sni: ?[*:0]const u8) ?*us_socket_t;
pub extern fn us_socket_from_fd(
ctx: *SocketContext,
ext_size: c_int,
fd: uws.LIBUS_SOCKET_DESCRIPTOR,
is_ipc: c_int,
) ?*us_socket_t;
pub extern fn us_socket_from_fd(ctx: *SocketContext, ext_size: c_int, fd: uws.LIBUS_SOCKET_DESCRIPTOR, is_ipc: c_int) ?*us_socket_t;
pub extern fn us_socket_get_error(ssl: i32, s: *uws.us_socket_t) c_int;
pub extern fn us_socket_is_established(ssl: i32, s: *uws.us_socket_t) i32;
};

View File

@@ -123,6 +123,10 @@ pub const SystemErrno = enum(u16) {
if (code >= max) return null;
return @enumFromInt(code);
}
pub fn to_uv_errno(this: SystemErrno) c_int {
return @intFromEnum(this);
}
};
pub const UV_E = struct {
pub const @"2BIG": i32 = @intFromEnum(SystemErrno.E2BIG);

View File

@@ -152,6 +152,10 @@ pub const SystemErrno = enum(u16) {
if (code >= max) return null;
return @enumFromInt(code);
}
pub fn to_uv_errno(this: SystemErrno) c_int {
return @intFromEnum(this);
}
};
pub const UV_E = struct {
pub const @"2BIG": i32 = @intFromEnum(SystemErrno.E2BIG);

View File

@@ -1093,6 +1093,235 @@ pub const SystemErrno = enum(u16) {
return @as(SystemErrno, @enumFromInt(code));
}
pub fn to_uv_errno(this: SystemErrno) c_int {
return @intFromEnum(@as(SystemErrno, switch (this) {
.SUCCESS => .SUCCESS,
.EPERM => .UV_EPERM,
.ENOENT => .UV_ENOENT,
.ESRCH => .UV_ESRCH,
.EINTR => .UV_EINTR,
.EIO => .UV_EIO,
.ENXIO => .UV_ENXIO,
.E2BIG => .UV_E2BIG,
.ENOEXEC => unreachable,
.EBADF => .UV_EBADF,
.ECHILD => unreachable,
.EAGAIN => .UV_EAGAIN,
.ENOMEM => .UV_ENOMEM,
.EACCES => .UV_EACCES,
.EFAULT => .UV_EFAULT,
.ENOTBLK => unreachable,
.EBUSY => .UV_EBUSY,
.EEXIST => .UV_EEXIST,
.EXDEV => .UV_EXDEV,
.ENODEV => .UV_ENODEV,
.ENOTDIR => .UV_ENOTDIR,
.EISDIR => .UV_EISDIR,
.EINVAL => .UV_EINVAL,
.ENFILE => .UV_ENFILE,
.EMFILE => .UV_EMFILE,
.ENOTTY => .UV_ENOTTY,
.ETXTBSY => .UV_ETXTBSY,
.EFBIG => .UV_EFBIG,
.ENOSPC => .UV_ENOSPC,
.ESPIPE => .UV_ESPIPE,
.EROFS => .UV_EROFS,
.EMLINK => .UV_EMLINK,
.EPIPE => .UV_EPIPE,
.EDOM => unreachable,
.ERANGE => .UV_ERANGE,
.EDEADLK => unreachable,
.ENAMETOOLONG => .UV_ENAMETOOLONG,
.ENOLCK => unreachable,
.ENOSYS => .UV_ENOSYS,
.ENOTEMPTY => .UV_ENOTEMPTY,
.ELOOP => .UV_ELOOP,
.EWOULDBLOCK => unreachable,
.ENOMSG => unreachable,
.EIDRM => unreachable,
.ECHRNG => unreachable,
.EL2NSYNC => unreachable,
.EL3HLT => unreachable,
.EL3RST => unreachable,
.ELNRNG => unreachable,
.EUNATCH => .UV_EUNATCH,
.ENOCSI => unreachable,
.EL2HLT => unreachable,
.EBADE => unreachable,
.EBADR => unreachable,
.EXFULL => unreachable,
.ENOANO => unreachable,
.EBADRQC => unreachable,
.EBADSLT => unreachable,
.EDEADLOCK => unreachable,
.EBFONT => unreachable,
.ENOSTR => unreachable,
.ENODATA => .UV_ENODATA,
.ETIME => unreachable,
.ENOSR => unreachable,
.ENONET => .UV_ENONET,
.ENOPKG => unreachable,
.EREMOTE => unreachable,
.ENOLINK => unreachable,
.EADV => unreachable,
.ESRMNT => unreachable,
.ECOMM => unreachable,
.EPROTO => .UV_EPROTO,
.EMULTIHOP => unreachable,
.EDOTDOT => unreachable,
.EBADMSG => unreachable,
.EOVERFLOW => .UV_EOVERFLOW,
.ENOTUNIQ => unreachable,
.EBADFD => unreachable,
.EREMCHG => unreachable,
.ELIBACC => unreachable,
.ELIBBAD => unreachable,
.ELIBSCN => unreachable,
.ELIBMAX => unreachable,
.ELIBEXEC => unreachable,
.EILSEQ => .UV_EILSEQ,
.ERESTART => unreachable,
.ESTRPIPE => unreachable,
.EUSERS => unreachable,
.ENOTSOCK => .UV_ENOTSOCK,
.EDESTADDRREQ => .UV_EDESTADDRREQ,
.EMSGSIZE => .UV_EMSGSIZE,
.EPROTOTYPE => .UV_EPROTOTYPE,
.ENOPROTOOPT => .UV_ENOPROTOOPT,
.EPROTONOSUPPORT => .UV_EPROTONOSUPPORT,
.ESOCKTNOSUPPORT => .UV_ESOCKTNOSUPPORT,
.ENOTSUP => .UV_ENOTSUP,
.EPFNOSUPPORT => unreachable,
.EAFNOSUPPORT => .UV_EAFNOSUPPORT,
.EADDRINUSE => .UV_EADDRINUSE,
.EADDRNOTAVAIL => .UV_EADDRNOTAVAIL,
.ENETDOWN => .UV_ENETDOWN,
.ENETUNREACH => .UV_ENETUNREACH,
.ENETRESET => unreachable,
.ECONNABORTED => .UV_ECONNABORTED,
.ECONNRESET => .UV_ECONNRESET,
.ENOBUFS => .UV_ENOBUFS,
.EISCONN => .UV_EISCONN,
.ENOTCONN => .UV_ENOTCONN,
.ESHUTDOWN => .UV_ESHUTDOWN,
.ETOOMANYREFS => unreachable,
.ETIMEDOUT => .UV_ETIMEDOUT,
.ECONNREFUSED => .UV_ECONNREFUSED,
.EHOSTDOWN => .UV_EHOSTDOWN,
.EHOSTUNREACH => .UV_EHOSTUNREACH,
.EALREADY => .UV_EALREADY,
.EINPROGRESS => unreachable,
.ESTALE => unreachable,
.EUCLEAN => unreachable,
.ENOTNAM => unreachable,
.ENAVAIL => unreachable,
.EISNAM => unreachable,
.EREMOTEIO => .UV_EREMOTEIO,
.EDQUOT => unreachable,
.ENOMEDIUM => unreachable,
.EMEDIUMTYPE => unreachable,
.ECANCELED => .UV_ECANCELED,
.ENOKEY => unreachable,
.EKEYEXPIRED => unreachable,
.EKEYREVOKED => unreachable,
.EKEYREJECTED => unreachable,
.EOWNERDEAD => unreachable,
.ENOTRECOVERABLE => unreachable,
.ERFKILL => unreachable,
.EHWPOISON => unreachable,
.EUNKNOWN => unreachable,
.ECHARSET => .UV_ECHARSET,
.EOF => .UV_EOF,
.UV_E2BIG => .UV_E2BIG,
.UV_EACCES => .UV_EACCES,
.UV_EADDRINUSE => .UV_EADDRINUSE,
.UV_EADDRNOTAVAIL => .UV_EADDRNOTAVAIL,
.UV_EAFNOSUPPORT => .UV_EAFNOSUPPORT,
.UV_EAGAIN => .UV_EAGAIN,
.UV_EAI_ADDRFAMILY => .UV_EAI_ADDRFAMILY,
.UV_EAI_AGAIN => .UV_EAI_AGAIN,
.UV_EAI_BADFLAGS => .UV_EAI_BADFLAGS,
.UV_EAI_BADHINTS => .UV_EAI_BADHINTS,
.UV_EAI_CANCELED => .UV_EAI_CANCELED,
.UV_EAI_FAIL => .UV_EAI_FAIL,
.UV_EAI_FAMILY => .UV_EAI_FAMILY,
.UV_EAI_MEMORY => .UV_EAI_MEMORY,
.UV_EAI_NODATA => .UV_EAI_NODATA,
.UV_EAI_NONAME => .UV_EAI_NONAME,
.UV_EAI_OVERFLOW => .UV_EAI_OVERFLOW,
.UV_EAI_PROTOCOL => .UV_EAI_PROTOCOL,
.UV_EAI_SERVICE => .UV_EAI_SERVICE,
.UV_EAI_SOCKTYPE => .UV_EAI_SOCKTYPE,
.UV_EALREADY => .UV_EALREADY,
.UV_EBADF => .UV_EBADF,
.UV_EBUSY => .UV_EBUSY,
.UV_ECANCELED => .UV_ECANCELED,
.UV_ECHARSET => .UV_ECHARSET,
.UV_ECONNABORTED => .UV_ECONNABORTED,
.UV_ECONNREFUSED => .UV_ECONNREFUSED,
.UV_ECONNRESET => .UV_ECONNRESET,
.UV_EDESTADDRREQ => .UV_EDESTADDRREQ,
.UV_EEXIST => .UV_EEXIST,
.UV_EFAULT => .UV_EFAULT,
.UV_EFBIG => .UV_EFBIG,
.UV_EHOSTUNREACH => .UV_EHOSTUNREACH,
.UV_EINVAL => .UV_EINVAL,
.UV_EINTR => .UV_EINTR,
.UV_EISCONN => .UV_EISCONN,
.UV_EIO => .UV_EIO,
.UV_ELOOP => .UV_ELOOP,
.UV_EISDIR => .UV_EISDIR,
.UV_EMSGSIZE => .UV_EMSGSIZE,
.UV_EMFILE => .UV_EMFILE,
.UV_ENETDOWN => .UV_ENETDOWN,
.UV_ENAMETOOLONG => .UV_ENAMETOOLONG,
.UV_ENFILE => .UV_ENFILE,
.UV_ENETUNREACH => .UV_ENETUNREACH,
.UV_ENODEV => .UV_ENODEV,
.UV_ENOBUFS => .UV_ENOBUFS,
.UV_ENOMEM => .UV_ENOMEM,
.UV_ENOENT => .UV_ENOENT,
.UV_ENOPROTOOPT => .UV_ENOPROTOOPT,
.UV_ENONET => .UV_ENONET,
.UV_ENOSYS => .UV_ENOSYS,
.UV_ENOSPC => .UV_ENOSPC,
.UV_ENOTDIR => .UV_ENOTDIR,
.UV_ENOTCONN => .UV_ENOTCONN,
.UV_ENOTSOCK => .UV_ENOTSOCK,
.UV_ENOTEMPTY => .UV_ENOTEMPTY,
.UV_EOVERFLOW => .UV_EOVERFLOW,
.UV_ENOTSUP => .UV_ENOTSUP,
.UV_EPIPE => .UV_EPIPE,
.UV_EPERM => .UV_EPERM,
.UV_EPROTONOSUPPORT => .UV_EPROTONOSUPPORT,
.UV_EPROTO => .UV_EPROTO,
.UV_ERANGE => .UV_ERANGE,
.UV_EPROTOTYPE => .UV_EPROTOTYPE,
.UV_ESHUTDOWN => .UV_ESHUTDOWN,
.UV_EROFS => .UV_EROFS,
.UV_ESRCH => .UV_ESRCH,
.UV_ESPIPE => .UV_ESPIPE,
.UV_ETXTBSY => .UV_ETXTBSY,
.UV_ETIMEDOUT => .UV_ETIMEDOUT,
.UV_UNKNOWN => .UV_UNKNOWN,
.UV_EXDEV => .UV_EXDEV,
.UV_ENXIO => .UV_ENXIO,
.UV_EOF => .UV_EOF,
.UV_EHOSTDOWN => .UV_EHOSTDOWN,
.UV_EMLINK => .UV_EMLINK,
.UV_ENOTTY => .UV_ENOTTY,
.UV_EREMOTEIO => .UV_EREMOTEIO,
.UV_EILSEQ => .UV_EILSEQ,
.UV_EFTYPE => .UV_EFTYPE,
.UV_ENODATA => .UV_ENODATA,
.UV_ESOCKTNOSUPPORT => .UV_ESOCKTNOSUPPORT,
.UV_ERRNO_MAX => .UV_ERRNO_MAX,
.UV_EUNATCH => .UV_EUNATCH,
.UV_ENOEXEC => .UV_ENOEXEC,
}));
}
};
pub const UV_E = struct {
@@ -1167,6 +1396,56 @@ pub const UV_E = struct {
pub const NOEXEC = -uv.UV_ENOEXEC;
};
export fn us_wsa_to_libuv_errno(code: c_int) c_int {
return @intFromEnum(switch (@as(Win32Error, @enumFromInt(code))) {
.SUCCESS => .SUCCESS,
Win32Error.WSAEINTR => SystemErrno.UV_EINTR,
Win32Error.WSAEBADF => SystemErrno.UV_EBADF,
Win32Error.WSAEACCES => SystemErrno.UV_EACCES,
Win32Error.WSAEFAULT => SystemErrno.UV_EFAULT,
Win32Error.WSAEINVAL => SystemErrno.UV_EINVAL,
Win32Error.WSAEMFILE => SystemErrno.UV_EMFILE,
Win32Error.WSAEWOULDBLOCK => SystemErrno.UV_EAGAIN,
Win32Error.WSAEINPROGRESS => SystemErrno.UV_EAGAIN,
Win32Error.WSAEALREADY => SystemErrno.UV_EALREADY,
Win32Error.WSAENOTSOCK => SystemErrno.UV_ENOTSOCK,
Win32Error.WSAEDESTADDRREQ => SystemErrno.UV_EDESTADDRREQ,
Win32Error.WSAEMSGSIZE => SystemErrno.UV_EMSGSIZE,
Win32Error.WSAEPROTOTYPE => SystemErrno.UV_EPROTOTYPE,
Win32Error.WSAENOPROTOOPT => SystemErrno.UV_ENOPROTOOPT,
Win32Error.WSAEPROTONOSUPPORT => SystemErrno.UV_EPROTONOSUPPORT,
Win32Error.WSAESOCKTNOSUPPORT => SystemErrno.UV_ESOCKTNOSUPPORT,
Win32Error.WSAEOPNOTSUPP => SystemErrno.UV_ENOTSUP,
Win32Error.WSAEPFNOSUPPORT => SystemErrno.UV_ENOTSUP,
Win32Error.WSAEAFNOSUPPORT => SystemErrno.UV_EAFNOSUPPORT,
Win32Error.WSAEADDRINUSE => SystemErrno.UV_EADDRINUSE,
Win32Error.WSAEADDRNOTAVAIL => SystemErrno.UV_EADDRNOTAVAIL,
Win32Error.WSAENETDOWN => SystemErrno.UV_ENETDOWN,
Win32Error.WSAENETUNREACH => SystemErrno.UV_ENETUNREACH,
// Win32Error.WSAENETRESET => SystemErrno.UV_ENETRESET,
Win32Error.WSAECONNABORTED => SystemErrno.UV_ECONNABORTED,
Win32Error.WSAECONNRESET => SystemErrno.UV_ECONNRESET,
Win32Error.WSAENOBUFS => SystemErrno.UV_ENOBUFS,
Win32Error.WSAEISCONN => SystemErrno.UV_EISCONN,
Win32Error.WSAENOTCONN => SystemErrno.UV_ENOTCONN,
Win32Error.WSAESHUTDOWN => SystemErrno.UV_ESHUTDOWN,
// Win32Error.WSAETOOMANYREFS => SystemErrno.UV_ETOOMANYREFS,
Win32Error.WSAETIMEDOUT => SystemErrno.UV_ETIMEDOUT,
Win32Error.WSAECONNREFUSED => SystemErrno.UV_ECONNREFUSED,
Win32Error.WSAELOOP => SystemErrno.UV_ELOOP,
Win32Error.WSAENAMETOOLONG => SystemErrno.UV_ENAMETOOLONG,
Win32Error.WSAEHOSTDOWN => SystemErrno.UV_EHOSTDOWN,
Win32Error.WSAEHOSTUNREACH => SystemErrno.UV_EHOSTUNREACH,
Win32Error.WSAENOTEMPTY => SystemErrno.UV_ENOTEMPTY,
// Win32Error.WSAEPROCLIM => SystemErrno.UV_EPROCLIM,
// Win32Error.WSAEUSERS => SystemErrno.UV_EUSERS,
// Win32Error.WSAEDQUOT => SystemErrno.UV_EDQUOT,
// Win32Error.WSAESTALE => SystemErrno.UV_ESTALE,
// Win32Error.WSAEREMOTE => SystemErrno.UV_EREMOTE,
else => bun.Output.panic("us_wsa_to_libuv_errno: unexpected code: {d}", .{code}),
});
}
const bun = @import("bun");
const std = @import("std");

View File

@@ -448,6 +448,7 @@ pub fn NewHTTPContext(comptime ssl: bool) type {
this.us_socket_context,
ActiveSocket.init(client).ptr(),
false, // dont allow half-open sockets
null,
);
client.allow_retry = false;
return socket;
@@ -482,6 +483,7 @@ pub fn NewHTTPContext(comptime ssl: bool) type {
this.us_socket_context,
ActiveSocket.init(client).ptr(),
false,
null,
);
client.allow_retry = false;
return socket;

View File

@@ -133,6 +133,7 @@ pub fn NewHTTPUpgradeClient(comptime ssl: bool) type {
client,
"tcp",
false,
null,
)) |out| {
// I don't think this case gets reached.
if (out.state == .failed) {

View File

@@ -231,7 +231,7 @@ const SocketHandlers: SocketHandler = {
callback(error);
}
self.emit("error", error);
if (!self.destroyed) process.nextTick(destroyNT, self, error);
},
open(socket) {
const self = socket.data;
@@ -477,7 +477,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
if (!data) return;
if (data._hadError) return;
data._hadError = true;
const bunTLS = this[bunTlsSymbol];
if (typeof bunTLS === "function") {
@@ -501,7 +500,6 @@ const ServerHandlers: SocketHandler<NetSocket> = {
}
}
SocketHandlers.error(socket, error, true);
data.server.emit("clientError", error, data);
},
timeout(socket) {
SocketHandlers.timeout(socket);

View File

@@ -914,7 +914,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
if (path.len > 0) {
debug("connecting to mysql with path", .{});
ptr.socket = .{
.SocketTCP = uws.SocketTCP.connectUnixAnon(path, ctx, ptr, false) catch |err| {
.SocketTCP = uws.SocketTCP.connectUnixAnon(path, ctx, ptr, false, null) catch |err| {
tls_config.deinit();
if (tls_ctx) |tls| {
tls.deinit(true);
@@ -926,7 +926,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
} else {
debug("connecting to mysql with hostname", .{});
ptr.socket = .{
.SocketTCP = uws.SocketTCP.connectAnon(hostname.slice(), port, ctx, ptr, false) catch |err| {
.SocketTCP = uws.SocketTCP.connectAnon(hostname.slice(), port, ctx, ptr, false, null) catch |err| {
tls_config.deinit();
if (tls_ctx) |tls| {
tls.deinit(true);

View File

@@ -734,7 +734,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
if (path.len > 0) {
ptr.socket = .{
.SocketTCP = uws.SocketTCP.connectUnixAnon(path, ctx, ptr, false) catch |err| {
.SocketTCP = uws.SocketTCP.connectUnixAnon(path, ctx, ptr, false, null) catch |err| {
tls_config.deinit();
if (tls_ctx) |tls| {
tls.deinit(true);
@@ -745,7 +745,7 @@ pub fn call(globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JS
};
} else {
ptr.socket = .{
.SocketTCP = uws.SocketTCP.connectAnon(hostname.slice(), port, ctx, ptr, false) catch |err| {
.SocketTCP = uws.SocketTCP.connectAnon(hostname.slice(), port, ctx, ptr, false, null) catch |err| {
tls_config.deinit();
if (tls_ctx) |tls| {
tls.deinit(true);

View File

@@ -11,9 +11,9 @@ const This = @This();
// into methods on `bun.FD`, and keeping this namespace to just overall stuff
// like `Error`, `Maybe`, `Tag`, and so on.
const platform_defs = switch (Environment.os) {
.mac => @import("./errno/darwin_errno.zig"),
.windows => @import("./errno/windows_errno.zig"),
.linux => @import("./errno/linux_errno.zig"),
.mac => @import("./errno/darwin_errno.zig"),
.wasm => {},
};
pub const workaround_symbols = @import("./workaround_missing_symbols.zig").current;

View File

@@ -217,7 +217,7 @@ pub fn msg(this: Error) ?[]const u8 {
pub fn toShellSystemError(this: Error) SystemError {
@setEvalBranchQuota(1_000_000);
var err = SystemError{
.errno = @as(c_int, this.errno) * -1,
.errno = this.errno,
.syscall = bun.String.static(@tagName(this.syscall)),
.message = .empty,
};
@@ -253,7 +253,7 @@ pub fn toShellSystemError(this: Error) SystemError {
/// Use this whenever the error will be sent to JavaScript instead of the shell variant above.
pub fn toSystemError(this: Error) SystemError {
var err = SystemError{
.errno = -%@as(c_int, this.errno),
.errno = this.errno,
.syscall = bun.String.static(@tagName(this.syscall)),
.message = .empty,
};

View File

@@ -118,6 +118,7 @@ pub const Address = union(enum) {
ctx,
client,
false,
null,
));
},
.host => |h| {
@@ -127,6 +128,7 @@ pub const Address = union(enum) {
ctx,
client,
false,
null,
));
},
}

View File

@@ -213,7 +213,7 @@ it("should reject on connection error, calling both connectError() and rejecting
var data = {};
connect({
data,
hostname: "localhost",
hostname: "127.0.0.1",
port: 55555,
socket: {
connectError(socket, error) {
@@ -288,7 +288,7 @@ it("should handle connection error", done => {
var data = {};
connect({
data,
hostname: "localhost",
hostname: "127.0.0.1",
port: 55555,
socket: {
connectError(socket, error) {

View File

@@ -0,0 +1,98 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
const common = require('../common');
if (common.isWindows) return; // TODO: BUN use better WSA api, 'connect' always returns ECONNREFUSED.
const fixtures = require('../common/fixtures');
const fs = require('fs');
const net = require('net');
const assert = require('assert');
// Test if ENOTSOCK is fired when trying to connect to a file which is not
// a socket.
let emptyTxt;
if (common.isWindows) {
// On Win, common.PIPE will be a named pipe, so we use an existing empty
// file instead
emptyTxt = fixtures.path('empty.txt');
} else {
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
// Keep the file name very short so that we don't exceed the 108 char limit
// on CI for a POSIX socket. Even though this isn't actually a socket file,
// the error will be different from the one we are expecting if we exceed the
// limit.
emptyTxt = `${tmpdir.path}0.txt`;
function cleanup() {
try {
fs.unlinkSync(emptyTxt);
} catch (e) {
assert.strictEqual(e.code, 'ENOENT');
}
}
process.on('exit', cleanup);
cleanup();
fs.writeFileSync(emptyTxt, '');
}
const notSocketClient = net.createConnection(emptyTxt, function() {
assert.fail('connection callback should not run');
});
notSocketClient.on('error', common.mustCall(function(err) {
assert(err.code === 'ENOTSOCK' || err.code === 'ECONNREFUSED',
`received ${err.code} instead of ENOTSOCK or ECONNREFUSED`);
}));
// Trying to connect to not-existing socket should result in ENOENT error
const noEntSocketClient = net.createConnection('no-ent-file', function() {
assert.fail('connection to non-existent socket, callback should not run');
});
noEntSocketClient.on('error', common.mustCall(function(err) {
assert.strictEqual(err.code, 'ENOENT');
}));
// On Windows or IBMi or when running as root,
// a chmod has no effect on named pipes
if (!common.isWindows && !common.isIBMi && process.getuid() !== 0) {
// Trying to connect to a socket one has no access to should result in EACCES
const accessServer = net.createServer(
common.mustNotCall('server callback should not run'));
accessServer.listen(common.PIPE, common.mustCall(function() {
fs.chmodSync(common.PIPE, 0);
const accessClient = net.createConnection(common.PIPE, function() {
assert.fail('connection should get EACCES, callback should not run');
});
accessClient.on('error', common.mustCall(function(err) {
assert.strictEqual(err.code, 'EACCES');
accessServer.close();
}));
}));
}

View File

@@ -0,0 +1,38 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const net = require('net');
const fs = require('fs');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
// Test UV_PIPE_NO_TRUNCATE
// See pipe_overlong_path in https://github.com/libuv/libuv/blob/master/test/test-pipe-bind-error.c
if (common.isWindows) {
common.skip('UV_PIPE_NO_TRUNCATE is not supported on window');
}
// See https://github.com/libuv/libuv/issues/4231
const pipePath = `${tmpdir.path}/${'x'.repeat(10000)}.sock`;
const server = net.createServer()
.listen(pipePath)
// It may work on some operating systems
.on('listening', () => {
// The socket file must exist
assert.ok(fs.existsSync(pipePath));
const socket = net.connect(pipePath, common.mustCall(() => {
socket.destroy();
server.close();
}));
})
.on('error', (error) => {
console.error(error);
assert.ok(error.code === 'EINVAL');
net.connect(pipePath)
.on('error', common.mustCall((error) => {
console.error(error);
assert.ok(error.code === 'EINVAL');
}));
});

View File

@@ -0,0 +1,51 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
const common = require('../common');
const assert = require('assert');
const net = require('net');
const SIZE = 2E6;
const N = 10;
const buf = Buffer.alloc(SIZE, 'a');
const server = net.createServer(function(socket) {
socket.setNoDelay();
socket.on('error', common.mustCall(() => socket.destroy()))
.on('close', common.mustCall(() => server.close()));
for (let i = 0; i < N; ++i) {
socket.write(buf, () => {});
}
socket.end();
}).listen(0, function() {
const conn = net.connect(this.address().port);
conn.on('data', function(buf) {
assert.strictEqual(conn, conn.pause());
setTimeout(function() {
conn.destroy();
}, 20);
});
});

View File

@@ -6,7 +6,7 @@ import { request } from "http";
import { join } from "path";
const tmp_dir = tmpdirSync();
it("throws ENAMETOOLONG when socket path exceeds platform-specific limit", () => {
it("throws ENOENT when socket path exceeds platform-specific limit", () => {
// this must be the filename specifically, because we add a workaround for the length limit on linux
const path = "a".repeat(
{
@@ -32,7 +32,7 @@ it("throws ENAMETOOLONG when socket path exceeds platform-specific limit", () =>
return new Response("hello");
},
}),
).toThrow("too long");
).toThrow(/^ENOENT: no such file or directory, listen 'a+'$/);
});
it("throws an error when the directory is not found", () => {