diff --git a/starboard/android/shared/BUILD.gn b/starboard/android/shared/BUILD.gn index d30f5130d369..39faadf9beba 100644 --- a/starboard/android/shared/BUILD.gn +++ b/starboard/android/shared/BUILD.gn @@ -385,6 +385,7 @@ static_library("starboard_platform") { "player_set_max_video_input_size.cc", "player_set_max_video_input_size.h", "player_set_playback_rate.cc", + "posix_emu/errno.cc", "posix_emu/file.cc", "posix_emu/pthread.cc", "posix_emu/stat.cc", diff --git a/starboard/android/shared/platform_configuration/BUILD.gn b/starboard/android/shared/platform_configuration/BUILD.gn index fb616c4e748b..9c7bc708fb56 100644 --- a/starboard/android/shared/platform_configuration/BUILD.gn +++ b/starboard/android/shared/platform_configuration/BUILD.gn @@ -21,7 +21,7 @@ config("platform_configuration") { defines = [] include_dirs = [ - # POSIX emulation headers + # POSIX emulation headers - these need to come *before* system include_dirs. "//starboard/android/shared/posix_emu/include", ] diff --git a/starboard/android/shared/posix_emu/errno.cc b/starboard/android/shared/posix_emu/errno.cc new file mode 100644 index 000000000000..b01df5634791 --- /dev/null +++ b/starboard/android/shared/posix_emu/errno.cc @@ -0,0 +1,19 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +int* __errno_location(void) { + return __errno(); +} diff --git a/starboard/android/shared/posix_emu/include/errno.h b/starboard/android/shared/posix_emu/include/errno.h new file mode 100644 index 000000000000..e091be6e382b --- /dev/null +++ b/starboard/android/shared/posix_emu/include/errno.h @@ -0,0 +1,31 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_ANDROID_SHARED_POSIX_EMU_INCLUDE_ERRNO_H_ +#define STARBOARD_ANDROID_SHARED_POSIX_EMU_INCLUDE_ERRNO_H_ + +#include_next // The AndroidSdk version of the same file. + +#ifdef __cplusplus +extern "C" { +#endif + +// __errno_location not available in Android NDK. +int* __errno_location(void); + +#ifdef __cplusplus +} +#endif + +#endif // STARBOARD_ANDROID_SHARED_POSIX_EMU_INCLUDE_ERRNO_H_ diff --git a/starboard/elf_loader/exported_symbols.cc b/starboard/elf_loader/exported_symbols.cc index 096b16527d8d..c73c55bab79c 100644 --- a/starboard/elf_loader/exported_symbols.cc +++ b/starboard/elf_loader/exported_symbols.cc @@ -14,6 +14,7 @@ #include "starboard/elf_loader/exported_symbols.h" +#include #include #include #include @@ -456,6 +457,7 @@ ExportedSymbols::ExportedSymbols() { #if SB_API_VERSION >= 16 // POSIX APIs + REGISTER_SYMBOL(__errno_location); REGISTER_SYMBOL(accept); REGISTER_SYMBOL(bind); REGISTER_SYMBOL(calloc); diff --git a/starboard/nplb/BUILD.gn b/starboard/nplb/BUILD.gn index 4ce7d0622894..5148a86fad58 100644 --- a/starboard/nplb/BUILD.gn +++ b/starboard/nplb/BUILD.gn @@ -167,6 +167,7 @@ target(gtest_target_type, "nplb") { "posix_compliance/posix_socket_bind_test.cc", "posix_compliance/posix_socket_connect_test.cc", "posix_compliance/posix_socket_create_test.cc", + "posix_compliance/posix_socket_errno_test.cc", "posix_compliance/posix_socket_helpers.cc", "posix_compliance/posix_socket_listen_test.cc", "posix_compliance/posix_socket_receive_test.cc", diff --git a/starboard/nplb/posix_compliance/posix_socket_errno_test.cc b/starboard/nplb/posix_compliance/posix_socket_errno_test.cc new file mode 100644 index 000000000000..a9cba3491e41 --- /dev/null +++ b/starboard/nplb/posix_compliance/posix_socket_errno_test.cc @@ -0,0 +1,69 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "starboard/common/log.h" +#include "starboard/nplb/posix_compliance/posix_socket_helpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace nplb { +namespace { + +TEST(PosixErrnoTest, CreateInvalidSocket) { + EXPECT_FALSE(socket(-1, SOCK_STREAM, IPPROTO_TCP) == 0); + EXPECT_TRUE(errno == EAFNOSUPPORT); + SB_DLOG(INFO) << "Failed to create invalid socket, errno = " + << strerror(errno); +} + +TEST(PosixErrnoTest, AcceptInvalidSocket) { + int invalid_socket_fd = -1; + EXPECT_FALSE(accept(invalid_socket_fd, NULL, NULL) == 0); + EXPECT_TRUE(errno == EBADF); + SB_DLOG(INFO) << "Failed to accept invalid socket, errno = " + << strerror(errno); +} + +TEST(PosixErrnoTest, ConnectUnavailableAddress) { + int socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ASSERT_TRUE(socket_fd > 0); + + sockaddr_in6 address = {}; +#if SB_HAS(IPV6) + EXPECT_TRUE( + PosixGetLocalAddressIPv4(reinterpret_cast(&address)) == 0 || + PosixGetLocalAddressIPv6(reinterpret_cast(&address)) == 0); +#else + EXPECT_TRUE(PosixGetLocalAddressIPv4(reinterpret_cast(&address)) == + 0); +#endif + + // Attempt to connect to an address where we expect connection to be refused + connect(socket_fd, (struct sockaddr*)&address, sizeof(address)); + + EXPECT_TRUE(errno == ECONNREFUSED || errno == EADDRNOTAVAIL || + errno == EINPROGRESS || errno == EINVAL); + SB_DLOG(INFO) << "Failed to connect to unavailable address, errno = " + << strerror(errno); + + close(socket_fd); +} +} // namespace +} // namespace nplb +} // namespace starboard diff --git a/starboard/shared/posix/socket_create.cc b/starboard/shared/posix/socket_create.cc index 5c0922c00768..83d02eb0beb3 100644 --- a/starboard/shared/posix/socket_create.cc +++ b/starboard/shared/posix/socket_create.cc @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/common/socket.h" - #include #include #include #include #include "starboard/common/log.h" +#include "starboard/common/socket.h" #include "starboard/shared/posix/handle_eintr.h" #include "starboard/shared/posix/set_non_blocking_internal.h" #include "starboard/shared/posix/socket_internal.h" diff --git a/starboard/shared/posix/socket_listen.cc b/starboard/shared/posix/socket_listen.cc index 19342134858a..d1b5d3c86654 100644 --- a/starboard/shared/posix/socket_listen.cc +++ b/starboard/shared/posix/socket_listen.cc @@ -48,7 +48,7 @@ SbSocketError SbSocketListen(SbSocket socket) { #endif int result = listen(socket->socket_fd, kMaxConn); if (result != 0) { - return (socket->error = sbposix::TranslateSocketErrno(result)); + return (socket->error = sbposix::TranslateSocketErrno(errno)); } return (socket->error = kSbSocketOk); diff --git a/starboard/shared/win32/posix_emu/socket.cc b/starboard/shared/win32/posix_emu/socket.cc index 4d57a04e95b4..c55afaef1c1b 100644 --- a/starboard/shared/win32/posix_emu/socket.cc +++ b/starboard/shared/win32/posix_emu/socket.cc @@ -70,16 +70,19 @@ int handle_db_put(FileOrSocket handle) { static FileOrSocket handle_db_get(int fd, bool erase) { FileOrSocket invalid_handle = {/*is_file=*/false, -1, INVALID_SOCKET}; if (fd < 0) { + _set_errno(EBADF); return invalid_handle; } EnterCriticalSection(&g_critical_section.critical_section_); if (g_map_addr == nullptr) { g_map_addr = new std::map(); + _set_errno(EBADF); return invalid_handle; } auto itr = g_map_addr->find(fd); if (itr == g_map_addr->end()) { + _set_errno(EBADF); return invalid_handle; } @@ -91,6 +94,140 @@ static FileOrSocket handle_db_get(int fd, bool erase) { return handle; } +// WSAGetLastError should be called immediately to retrieve the extended error +// code for the failing function call. +// https://learn.microsoft.com/en-us/windows/win32/winsock/error-codes-errno-h-errno-and-wsagetlasterror-2 +static void set_errno() { + int winsockError = WSAGetLastError(); + int sockError = 0; + + // The error codes returned by Windows Sockets are similar to UNIX socket + // error code constants, but the constants are all prefixed with WSA. So in + // Winsock applications the WSAEWOULDBLOCK error code would be returned, while + // in UNIX applications the EWOULDBLOCK error code would be returned. The + // errno values in a WIN32 are a subset of the values for errno in UNIX + // systems. + switch (winsockError) { + case WSAEINTR: // Interrupted function call + sockError = EINTR; + break; + case WSAEBADF: // WSAEBADF + sockError = EBADF; + break; + case WSAEACCES: // WSAEACCES + sockError = EACCES; + break; + case WSAEFAULT: // Bad address + sockError = EFAULT; + break; + case WSAEINVAL: // Invalid argument + sockError = EINVAL; + break; + case WSAEMFILE: // Too many open files + sockError = EMFILE; + break; + case WSAEWOULDBLOCK: // Operation would block + sockError = EWOULDBLOCK; + break; + case WSAEINPROGRESS: // Operation now in progress + sockError = EINPROGRESS; + break; + case WSAEALREADY: // Operation already in progress + sockError = EALREADY; + break; + case WSAENOTSOCK: // Socket operation on non-socket + sockError = ENOTSOCK; + break; + case WSAEDESTADDRREQ: // Destination address required + sockError = EDESTADDRREQ; + break; + case WSAEMSGSIZE: // Message too long + sockError = EMSGSIZE; + break; + case WSAEPROTOTYPE: // Protocol wrong type for socket + sockError = EPROTOTYPE; + break; + case WSAENOPROTOOPT: // Bad protocol option + sockError = ENOPROTOOPT; + break; + case WSAEPROTONOSUPPORT: // Protocol not supported + sockError = EPROTONOSUPPORT; + break; + case WSAEOPNOTSUPP: // Operation not supported + sockError = EOPNOTSUPP; + break; + case WSAEAFNOSUPPORT: // Address family not supported by protocol family + sockError = EAFNOSUPPORT; + break; + case WSAEADDRINUSE: // Address already in use + sockError = EADDRINUSE; + break; + case WSAEADDRNOTAVAIL: // Cannot assign requested address + sockError = EADDRNOTAVAIL; + break; + case WSAENETDOWN: // Network is down + sockError = ENETDOWN; + break; + case WSAENETUNREACH: // Network is unreachable + sockError = ENETUNREACH; + break; + case WSAENETRESET: // Network dropped connection on reset + sockError = ENETRESET; + break; + case WSAECONNABORTED: // Software caused connection abort + sockError = ECONNABORTED; + break; + case WSAECONNRESET: // Connection reset by peer + sockError = ECONNRESET; + break; + case WSAENOBUFS: // No buffer space available + sockError = ENOBUFS; + break; + case WSAEISCONN: // Socket is already connected + sockError = EISCONN; + break; + case WSAENOTCONN: // Socket is not connected + sockError = ENOTCONN; + break; + case WSAETIMEDOUT: // Connection timed out + sockError = ETIMEDOUT; + break; + case WSAECONNREFUSED: // Connection refused + sockError = ECONNREFUSED; + break; + case WSAELOOP: // WSAELOOP + sockError = ELOOP; + break; + case WSAENAMETOOLONG: // WSAENAMETOOLONG + sockError = ENAMETOOLONG; + break; + case WSAEHOSTUNREACH: // No route to host + sockError = EHOSTUNREACH; + break; + case WSAENOTEMPTY: // WSAENOTEMPTY + sockError = ENOTEMPTY; + break; + case WSAHOST_NOT_FOUND: // Host not found + sockError = HOST_NOT_FOUND; + break; + case WSATRY_AGAIN: // Non-authoritative host not found + sockError = TRY_AGAIN; + break; + case WSANO_RECOVERY: // This is a non-recoverable error + sockError = NO_RECOVERY; + break; + case WSANO_DATA: // Valid name, no data record of requested type + sockError = NO_DATA; + break; + default: + SB_DLOG(WARNING) << "Unknown socket error."; + break; + } + + _set_errno(sockError); + SB_DLOG(INFO) << "Encounter socket error: " << sockError; +} + /////////////////////////////////////////////////////////////////////////////// // Implementations below exposed externally in pure C for emulation. /////////////////////////////////////////////////////////////////////////////// @@ -102,8 +239,7 @@ int sb_socket(int domain, int type, int protocol) { // socket() returns a handle to a kernel object instead SOCKET socket_handle = socket(domain, type, protocol); if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error - errno = WSAGetLastError(); + set_errno(); return -1; } @@ -139,10 +275,13 @@ int close(int fd) { FileOrSocket handle = handle_db_get(fd, true); if (!handle.is_file && handle.socket == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } else if (!handle.is_file) { - return closesocket(handle.socket); + int result = closesocket(handle.socket); + if (result == SOCKET_ERROR) { + set_errno(); + } + return result; } // This is then a file handle, so use Windows `_close` API. @@ -200,37 +339,38 @@ int write(int fd, const void* buffer, unsigned int count) { int sb_bind(int socket, const struct sockaddr* address, socklen_t address_len) { SOCKET socket_handle = handle_db_get(socket, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } int result = bind(socket_handle, address, address_len); - errno = WSAGetLastError(); + if (result == SOCKET_ERROR) { + set_errno(); + } return result; } int sb_listen(int socket, int backlog) { SOCKET socket_handle = handle_db_get(socket, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } int result = listen(socket_handle, backlog); - errno = WSAGetLastError(); + if (result == SOCKET_ERROR) { + set_errno(); + } return result; } int sb_accept(int socket, sockaddr* addr, int* addrlen) { SOCKET socket_handle = handle_db_get(socket, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } SOCKET accept_handle = accept(socket_handle, addr, addrlen); if (accept_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error + set_errno(); return -1; } @@ -241,35 +381,40 @@ int sb_accept(int socket, sockaddr* addr, int* addrlen) { int sb_connect(int socket, sockaddr* name, int namelen) { SOCKET socket_handle = handle_db_get(socket, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } int result = connect(socket_handle, name, namelen); - errno = WSAGetLastError(); + if (result == SOCKET_ERROR) { + set_errno(); + } return result; } int sb_send(int sockfd, const void* buf, size_t len, int flags) { SOCKET socket_handle = handle_db_get(sockfd, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } + int result = send(socket_handle, reinterpret_cast(buf), len, flags); - errno = WSAGetLastError(); + if (result == SOCKET_ERROR) { + set_errno(); + } return result; } int sb_recv(int sockfd, void* buf, size_t len, int flags) { SOCKET socket_handle = handle_db_get(sockfd, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } + int result = recv(socket_handle, reinterpret_cast(buf), len, flags); - errno = WSAGetLastError(); + if (result == SOCKET_ERROR) { + set_errno(); + } return result; } @@ -281,12 +426,14 @@ int sb_sendto(int sockfd, socklen_t dest_len) { SOCKET socket_handle = handle_db_get(sockfd, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } + int result = sendto(socket_handle, reinterpret_cast(buf), len, flags, dest_addr, dest_len); - errno = WSAGetLastError(); + if (result == SOCKET_ERROR) { + set_errno(); + } return result; } @@ -298,12 +445,14 @@ int sb_recvfrom(int sockfd, socklen_t* address_len) { SOCKET socket_handle = handle_db_get(sockfd, false).socket; if (socket_handle == INVALID_SOCKET) { - // TODO: update errno with file operation error return -1; } + int result = recvfrom(socket_handle, reinterpret_cast(buf), len, flags, address, address_len); - errno = WSAGetLastError(); + if (result == SOCKET_ERROR) { + set_errno(); + } return result; } @@ -321,14 +470,10 @@ int sb_setsockopt(int socket, int result = setsockopt(handle.socket, level, option_name, reinterpret_cast(option_value), option_len); - // TODO(b/321999529): Windows returns SOCKET_ERROR on failure. The specific - // error code can be retrieved by calling WSAGetLastError(), and Posix returns - // -1 on failure and sets errno to the error’s value. if (result == SOCKET_ERROR) { - errno = WSAGetLastError(); - return -1; + set_errno(); } - return 0; + return result; } int sb_fcntl(int fd, int cmd, ... /*arg*/) { @@ -350,5 +495,4 @@ int sb_fcntl(int fd, int cmd, ... /*arg*/) { } return 0; } - } // extern "C" diff --git a/starboard/tools/api_leak_detector/api_leak_detector.py b/starboard/tools/api_leak_detector/api_leak_detector.py index a31bf0e59f81..15bcfe76960e 100755 --- a/starboard/tools/api_leak_detector/api_leak_detector.py +++ b/starboard/tools/api_leak_detector/api_leak_detector.py @@ -87,6 +87,7 @@ # Allowed POSIX symbols in Starboard 16 _ALLOWED_SB16_POSIX_SYMBOLS = [ + '__errno_location', 'accept', 'bind', 'calloc', diff --git a/starboard/tools/api_leak_detector/stub/debug/docker_debian10_manifest b/starboard/tools/api_leak_detector/stub/debug/docker_debian10_manifest index 016ab12af8a2..e27b45266ccf 100644 --- a/starboard/tools/api_leak_detector/stub/debug/docker_debian10_manifest +++ b/starboard/tools/api_leak_detector/stub/debug/docker_debian10_manifest @@ -26,7 +26,6 @@ __ctype_get_mb_cur_max __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/debug/gn_built_docker_debian11_manifest b/starboard/tools/api_leak_detector/stub/debug/gn_built_docker_debian11_manifest index 7e7d6342ec15..29403aaefcff 100644 --- a/starboard/tools/api_leak_detector/stub/debug/gn_built_docker_debian11_manifest +++ b/starboard/tools/api_leak_detector/stub/debug/gn_built_docker_debian11_manifest @@ -26,7 +26,6 @@ __ctype_get_mb_cur_max __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/debug/manifest b/starboard/tools/api_leak_detector/stub/debug/manifest index 623b073983f2..9896fd581e18 100644 --- a/starboard/tools/api_leak_detector/stub/debug/manifest +++ b/starboard/tools/api_leak_detector/stub/debug/manifest @@ -26,7 +26,6 @@ __ctype_get_mb_cur_max __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/devel/docker_debian10_manifest b/starboard/tools/api_leak_detector/stub/devel/docker_debian10_manifest index 670a82092323..ed0dbbd11652 100644 --- a/starboard/tools/api_leak_detector/stub/devel/docker_debian10_manifest +++ b/starboard/tools/api_leak_detector/stub/devel/docker_debian10_manifest @@ -27,7 +27,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/devel/gn_built_docker_debian11_manifest b/starboard/tools/api_leak_detector/stub/devel/gn_built_docker_debian11_manifest index 59f1232d16d6..480ca8fae802 100644 --- a/starboard/tools/api_leak_detector/stub/devel/gn_built_docker_debian11_manifest +++ b/starboard/tools/api_leak_detector/stub/devel/gn_built_docker_debian11_manifest @@ -27,7 +27,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/devel/manifest b/starboard/tools/api_leak_detector/stub/devel/manifest index 8f01ab5c8d50..d55fed99e981 100644 --- a/starboard/tools/api_leak_detector/stub/devel/manifest +++ b/starboard/tools/api_leak_detector/stub/devel/manifest @@ -27,7 +27,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/gold/docker_debian10_manifest b/starboard/tools/api_leak_detector/stub/gold/docker_debian10_manifest index 02cd3d4a421c..7de42d06b67c 100644 --- a/starboard/tools/api_leak_detector/stub/gold/docker_debian10_manifest +++ b/starboard/tools/api_leak_detector/stub/gold/docker_debian10_manifest @@ -25,7 +25,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/gold/gn_built_docker_debian11_manifest b/starboard/tools/api_leak_detector/stub/gold/gn_built_docker_debian11_manifest index 926e11979a5f..fad0a61a385e 100644 --- a/starboard/tools/api_leak_detector/stub/gold/gn_built_docker_debian11_manifest +++ b/starboard/tools/api_leak_detector/stub/gold/gn_built_docker_debian11_manifest @@ -25,7 +25,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/gold/manifest b/starboard/tools/api_leak_detector/stub/gold/manifest index f0fb7f9d342f..5daffb4f64e0 100644 --- a/starboard/tools/api_leak_detector/stub/gold/manifest +++ b/starboard/tools/api_leak_detector/stub/gold/manifest @@ -25,7 +25,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/qa/docker_debian10_manifest b/starboard/tools/api_leak_detector/stub/qa/docker_debian10_manifest index 495b53fd8d23..cf160cb8c526 100644 --- a/starboard/tools/api_leak_detector/stub/qa/docker_debian10_manifest +++ b/starboard/tools/api_leak_detector/stub/qa/docker_debian10_manifest @@ -26,7 +26,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/qa/gn_built_docker_debian11_manifest b/starboard/tools/api_leak_detector/stub/qa/gn_built_docker_debian11_manifest index a1789127a2cb..21532b8af3a1 100644 --- a/starboard/tools/api_leak_detector/stub/qa/gn_built_docker_debian11_manifest +++ b/starboard/tools/api_leak_detector/stub/qa/gn_built_docker_debian11_manifest @@ -26,7 +26,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/starboard/tools/api_leak_detector/stub/qa/manifest b/starboard/tools/api_leak_detector/stub/qa/manifest index 610cc36c596f..bff8901e7ffc 100644 --- a/starboard/tools/api_leak_detector/stub/qa/manifest +++ b/starboard/tools/api_leak_detector/stub/qa/manifest @@ -26,7 +26,6 @@ __ctype_toupper_loc __cxa_atexit __cxa_finalize __duplocale -__errno_location __freelocale __fxstat64 __gmon_start__ diff --git a/third_party/musl/include/errno.h b/third_party/musl/include/errno.h index 0361b33ad348..1aed0a29a32e 100644 --- a/third_party/musl/include/errno.h +++ b/third_party/musl/include/errno.h @@ -24,4 +24,3 @@ extern char *program_invocation_short_name, *program_invocation_name; #endif #endif - diff --git a/third_party/musl/src/include/errno.h b/third_party/musl/src/include/errno.h index 8ec493777da9..c1f68fa18506 100644 --- a/third_party/musl/src/include/errno.h +++ b/third_party/musl/src/include/errno.h @@ -3,6 +3,9 @@ #include "../../include/errno.h" +// Prior to SB 16, ___errno_location was a weak alias for __errno_location in musl. +// Starting with SB 16, we no longer implement __errno_location in musl. Instead, we retrieve the __errno_location symbols from the system. +#if SB_API_VERSION < 16 #ifdef __GNUC__ __attribute__((const)) #endif @@ -10,5 +13,6 @@ hidden int *___errno_location(void); #undef errno #define errno (*___errno_location()) +#endif // SB_API_VERSION < 16 -#endif +#endif \ No newline at end of file diff --git a/third_party/musl/src/starboard/errno/__errno_location.c b/third_party/musl/src/starboard/errno/__errno_location.c index 6cca91f61fb2..7990d70701ae 100644 --- a/third_party/musl/src/starboard/errno/__errno_location.c +++ b/third_party/musl/src/starboard/errno/__errno_location.c @@ -1,3 +1,4 @@ +#if SB_API_VERSION < 16 #include #include @@ -19,6 +20,8 @@ void initialize_errno_key(void) { // This key will then by used by every thread to set, and get, their instance of // errno from thread-local storage. +// This function does not take much effect in musl, use SbSystemGetLastError to set +// errno instead. int *__errno_location(void) { int result = pthread_once(&g_errno_once, &initialize_errno_key); SB_DCHECK(result == 0); @@ -41,3 +44,5 @@ int *__errno_location(void) { } weak_alias(__errno_location, ___errno_location); + +#endif // SB_API_VERSION < 16 \ No newline at end of file diff --git a/third_party/musl/src/starboard/network/socket.c b/third_party/musl/src/starboard/network/socket.c index 9d8177404bbe..a86a1176fcf1 100644 --- a/third_party/musl/src/starboard/network/socket.c +++ b/third_party/musl/src/starboard/network/socket.c @@ -25,6 +25,7 @@ #include #include +#include "starboard/common/log.h" #include "starboard/file.h" #include "starboard/socket.h" #include "starboard/system.h" @@ -173,6 +174,7 @@ int TranslateSocketErrnoSbToPosix(SbSocketError sbError) { int ConvertSocketAddressPosixToSb(const struct sockaddr* address, SbSocketAddress* sbAddress){ if (address == NULL){ + errno = EINVAL; return -1; } struct sockaddr_in* addr_in = (struct sockaddr_in*)address; @@ -195,6 +197,7 @@ int ConvertSocketAddressPosixToSb(const struct sockaddr* address, SbSocketAddres int ConvertSocketAddressSbToPosix(const SbSocketAddress* sbAddress, struct sockaddr* address){ if (sbAddress == NULL){ + errno = EINVAL; return -1; } struct sockaddr_in* addr_in = (struct sockaddr_in*)address; @@ -400,12 +403,14 @@ int open(const char* path, int oflag, ...) { value->file = SbFileOpen(path, open_flags, &out_created, &out_error); if (!SbFileIsValid(value->file)){ + errno = SbSystemGetLastError(); free(value); return -1; } int result = put(value); if (result <= 0){ + errno = EBADF; SbFileClose(value->file); free(value); } @@ -460,6 +465,7 @@ int socket(int domain, int type, int protocol){ address_type = kSbSocketAddressTypeIpv6; break; default: + errno = EAFNOSUPPORT; return -1; } switch (protocol){ @@ -470,6 +476,7 @@ int socket(int domain, int type, int protocol){ socket_protocol = kSbSocketProtocolUdp; break; default: + errno = EAFNOSUPPORT; return -1; } @@ -478,6 +485,7 @@ int socket(int domain, int type, int protocol){ value->is_file = false; value->socket = SbSocketCreate(address_type, socket_protocol); if (!SbSocketIsValid(value->socket)){ + errno = SbSystemGetLastError(); free(value); return -1; } @@ -492,10 +500,12 @@ int socket(int domain, int type, int protocol){ int close(int fd){ if (fd <= 0) { + errno = EBADF; return -1; } FileOrSocket* valueptr = NULL; if (get(fd, true, &valueptr) != 0) { + errno = EBADF; return -1; } if (valueptr != NULL) { @@ -506,19 +516,22 @@ int close(int fd){ result = SbFileClose(valueptr->file); } if (!result){ + errno = EBADF; return -1; } return 0; } + errno = EBADF; return -1; } int bind(int socket, const struct sockaddr* address, socklen_t address_len) { - if (address == NULL || socket <= 0){ + if (address == NULL){ + errno = EINVAL; return -1; } FileOrSocket *fileOrSock = NULL; - if (get(socket, false, &fileOrSock) != 0){ + if (socket <= 0 || get(socket, false, &fileOrSock) != 0){ errno = EBADF; return -1; } @@ -541,6 +554,7 @@ int bind(int socket, const struct sockaddr* address, socklen_t address_len) { int listen(int socket, int backlog) { if (socket <= 0){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL; @@ -564,6 +578,7 @@ int listen(int socket, int backlog) { int accept(int socket, struct sockaddr* addr, socklen_t* addrlen) { if (socket <= 0){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL; @@ -581,6 +596,7 @@ int accept(int socket, struct sockaddr* addr, socklen_t* addrlen) { value->is_file = false; value->socket = SbSocketAccept(fileOrSock->socket); if (!SbSocketIsValid(value->socket)){ + errno = SbSystemGetLastError(); free(value); return -1; } @@ -590,6 +606,7 @@ int accept(int socket, struct sockaddr* addr, socklen_t* addrlen) { int connect(int socket, const struct sockaddr* name, socklen_t namelen) { if (socket <= 0 || name == NULL){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL; @@ -616,6 +633,7 @@ int connect(int socket, const struct sockaddr* name, socklen_t namelen) { ssize_t send(int sockfd, const void* buf, size_t len, int flags) { if (sockfd <= 0){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL; @@ -628,13 +646,19 @@ ssize_t send(int sockfd, const void* buf, size_t len, int flags) { return -1; } - return SbSocketSendTo(fileOrSock->socket, buf, len, NULL); + int result = SbSocketSendTo(fileOrSock->socket, buf, len, NULL); + if(result == -1) { + errno = SbSystemGetLastError(); + } + + return result; } ssize_t sendto(int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t dest_len) { if (sockfd <= 0){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL; @@ -650,11 +674,17 @@ ssize_t sendto(int sockfd, const void* buf, size_t len, int flags, SbSocketAddress local_address = {0}; ConvertSocketAddressPosixToSb(dest_addr, &local_address); - return SbSocketSendTo(fileOrSock->socket, buf, len, dest_addr == NULL? NULL: &local_address); + int result = SbSocketSendTo(fileOrSock->socket, buf, len, dest_addr == NULL? NULL: &local_address); + if(result == -1) { + errno = SbSystemGetLastError(); + } + + return result; } ssize_t recv(int sockfd, void* buf, size_t len, int flags) { if (sockfd <= 0){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL; @@ -667,7 +697,12 @@ ssize_t recv(int sockfd, void* buf, size_t len, int flags) { return -1; } - return SbSocketReceiveFrom(fileOrSock->socket, buf, len, NULL); + int result = SbSocketReceiveFrom(fileOrSock->socket, buf, len, NULL); + if(result == -1) { + errno = SbSystemGetLastError(); + } + + return result; } ssize_t recvfrom(int sockfd, @@ -692,11 +727,17 @@ ssize_t recvfrom(int sockfd, SbSocketAddress local_address = {0}; ConvertSocketAddressPosixToSb(address, &local_address); - return SbSocketReceiveFrom(fileOrSock->socket, buf, len, address == NULL? NULL: &local_address); + int result = SbSocketReceiveFrom(fileOrSock->socket, buf, len, address == NULL? NULL: &local_address); + if(result == -1) { + errno = SbSystemGetLastError(); + } + + return result; } int getsockname(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict addrlen){ if (sockfd <= 0){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL; @@ -716,6 +757,7 @@ int getsockname(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict int setsockopt (int sockfd, int level, int optname, const void* optval, socklen_t optlen){ if (sockfd <= 0){ + errno = EBADF; return -1; } FileOrSocket *fileOrSock = NULL;