@@ -1910,7 +1910,7 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19101910 int total_rx = 0 ;
19111911 int poll_count = 0 ;
19121912 int bytes_to_tcp_recved;
1913- size_t total_iov_sz = 1 ;
1913+ size_t total_iov_sz = 0 ;
19141914 int out_flags = 0 ;
19151915 int in_flags = *p_flags;
19161916 bool block_this_run = BLOCK_THIS_RUN (m_b_blocking, in_flags);
@@ -1932,6 +1932,18 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19321932 TAKE_T_RX_START;
19331933#endif
19341934
1935+ /* In general, without any special flags, socket options, or ioctls being set,
1936+ * a recv call on a blocking TCP socket will return any number of bytes less than
1937+ * or equal to the size being requested. But unless the socket is closed remotely,
1938+ * interrupted by signal, or in an error state,
1939+ * it will block until at least 1 byte is available.
1940+ * With MSG_ERRQUEUE flag user application can request just information from
1941+ * error queue without any income data.
1942+ */
1943+ if (p_iov && (sz_iov > 0 )) {
1944+ total_iov_sz = 1 ;
1945+ }
1946+
19351947 if (unlikely ((in_flags & MSG_WAITALL) && !(in_flags & MSG_PEEK))) {
19361948 total_iov_sz = 0 ;
19371949 for (int i = 0 ; i < sz_iov; i++) {
@@ -1942,13 +1954,22 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19421954 }
19431955
19441956 si_tcp_logfunc (" rx: iov=%p niovs=%d" , p_iov, sz_iov);
1945- /* poll rx queue till we have something */
1957+
1958+ /* poll rx queue till we have something */
19461959 lock_tcp_con ();
1960+ if (__msg) {
1961+ handle_cmsg (__msg, in_flags);
1962+ if (__msg->msg_controllen == 0 ) {
1963+ errno = EAGAIN;
1964+ unlock_tcp_con ();
1965+ return -1 ;
1966+ }
1967+ }
19471968 return_reuse_buffers_postponed ();
19481969 unlock_tcp_con ();
19491970
19501971 while (m_rx_ready_byte_count < total_iov_sz) {
1951- if (unlikely (g_b_exit ||!is_rtr () || (rx_wait_lockless (poll_count, block_this_run) < 0 ))) {
1972+ if (unlikely (g_b_exit || !is_rtr () || (rx_wait_lockless (poll_count, block_this_run) < 0 ))) {
19521973 return handle_rx_error (block_this_run);
19531974 }
19541975 }
@@ -1957,8 +1978,9 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19571978
19581979 si_tcp_logfunc (" something in rx queues: %d %p" , m_n_rx_pkt_ready_list_count, m_rx_pkt_ready_list.front ());
19591980
1960- total_rx = dequeue_packet (p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
1961- if (__msg) handle_cmsg (__msg, in_flags);
1981+ if (total_iov_sz > 0 ) {
1982+ total_rx = dequeue_packet (p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
1983+ }
19621984
19631985 /*
19641986 * RCVBUFF Accounting: Going 'out' of the internal buffer: if some bytes are not tcp_recved yet - do that.
0 commit comments