From 0d8187e25a97a856504cc476db5ea26771d6181e Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Fri, 13 Mar 2026 10:34:42 -0300 Subject: [PATCH] Use MSG_DONTWAIT instead of fcntl with O_NONBLOCK for sockets in sending/receiving On Linux, FreeBSD, OpenBSD and other systems, it's possible to have a non-blocking behavior on sockets using the flag MSG_DONTWAIT on sending and receiving functions per syscall, without needing to set the socket in a non-blocking state globally using ioctl or fcntl. This change will save a few syscalls to achieve the same results. --- include/asio/detail/impl/socket_ops.ipp | 27 +++++++++++++++++++ .../asio/detail/reactive_socket_service.hpp | 16 +++++++++-- .../detail/reactive_socket_service_base.hpp | 24 ++++++++++++++--- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/include/asio/detail/impl/socket_ops.ipp b/include/asio/detail/impl/socket_ops.ipp index 3bac4b4ba6..3ea50a0c3b 100644 --- a/include/asio/detail/impl/socket_ops.ipp +++ b/include/asio/detail/impl/socket_ops.ipp @@ -1007,6 +1007,9 @@ bool non_blocking_recv(socket_type s, buf* bufs, size_t count, int flags, bool is_stream, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Read some data. @@ -1045,6 +1048,9 @@ bool non_blocking_recv1(socket_type s, void* data, size_t size, int flags, bool is_stream, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Read some data. @@ -1256,6 +1262,9 @@ bool non_blocking_recvfrom(socket_type s, buf* bufs, size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Read some data. @@ -1288,6 +1297,9 @@ bool non_blocking_recvfrom1(socket_type s, void* data, size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Read some data. @@ -1401,6 +1413,9 @@ bool non_blocking_recvmsg(socket_type s, buf* bufs, size_t count, int in_flags, int& out_flags, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + in_flags |= MSG_DONTWAIT; +#endif for (;;) { // Read some data. @@ -1597,6 +1612,9 @@ bool non_blocking_send(socket_type s, const buf* bufs, size_t count, int flags, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Write some data. @@ -1628,6 +1646,9 @@ bool non_blocking_send1(socket_type s, const void* data, size_t size, int flags, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Write some data. @@ -1808,6 +1829,9 @@ bool non_blocking_sendto(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Write some data. @@ -1841,6 +1865,9 @@ bool non_blocking_sendto1(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred) { +#if defined(MSG_DONTWAIT) + flags |= MSG_DONTWAIT; +#endif for (;;) { // Write some data. diff --git a/include/asio/detail/reactive_socket_service.hpp b/include/asio/detail/reactive_socket_service.hpp index b49a44f177..9aecfdf3e0 100644 --- a/include/asio/detail/reactive_socket_service.hpp +++ b/include/asio/detail/reactive_socket_service.hpp @@ -307,8 +307,14 @@ class reactive_socket_service : ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send_to")); +#if defined(MSG_DONTWAIT) + constexpr bool has_msg_dontwait = true; +#else + constexpr bool has_msg_dontwait = false; +#endif + start_op(impl, reactor::write_op, p.p, - is_continuation, true, false, true, &io_ex, 0); + is_continuation, true, false, !has_msg_dontwait, &io_ex, 0); p.v = p.p = 0; } @@ -430,10 +436,16 @@ class reactive_socket_service : ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_from")); +#if defined(MSG_DONTWAIT) + constexpr bool has_msg_dontwait = true; +#else + constexpr bool has_msg_dontwait = false; +#endif + start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, - p.p, is_continuation, true, false, true, &io_ex, 0); + p.p, is_continuation, true, false, !has_msg_dontwait, &io_ex, 0); p.v = p.p = 0; } diff --git a/include/asio/detail/reactive_socket_service_base.hpp b/include/asio/detail/reactive_socket_service_base.hpp index 80ab9f5b3e..188aff585f 100644 --- a/include/asio/detail/reactive_socket_service_base.hpp +++ b/include/asio/detail/reactive_socket_service_base.hpp @@ -313,10 +313,16 @@ class reactive_socket_service_base ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send")); +#if defined(MSG_DONTWAIT) + constexpr bool has_msg_dontwait = true; +#else + constexpr bool has_msg_dontwait = false; +#endif + start_op(impl, reactor::write_op, p.p, is_continuation, true, ((impl.state_ & socket_ops::stream_oriented) && buffer_sequence_adapter::all_empty(buffers)), true, &io_ex, 0); + ConstBufferSequence>::all_empty(buffers)), !has_msg_dontwait, &io_ex, 0); p.v = p.p = 0; } @@ -419,6 +425,12 @@ class reactive_socket_service_base ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive")); +#if defined(MSG_DONTWAIT) + constexpr bool has_msg_dontwait = true; +#else + constexpr bool has_msg_dontwait = false; +#endif + start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, @@ -426,7 +438,7 @@ class reactive_socket_service_base (flags & socket_base::message_out_of_band) == 0, ((impl.state_ & socket_ops::stream_oriented) && buffer_sequence_adapter::all_empty(buffers)), true, &io_ex, 0); + MutableBufferSequence>::all_empty(buffers)), !has_msg_dontwait, &io_ex, 0); p.v = p.p = 0; } @@ -530,12 +542,18 @@ class reactive_socket_service_base ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_with_flags")); +#if defined(MSG_DONTWAIT) + constexpr bool has_msg_dontwait = true; +#else + constexpr bool has_msg_dontwait = false; +#endif + start_op(impl, (in_flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, p.p, is_continuation, (in_flags & socket_base::message_out_of_band) == 0, - false, true, &io_ex, 0); + false, !has_msg_dontwait, &io_ex, 0); p.v = p.p = 0; }