@@ -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,23 +1932,43 @@ 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- if (unlikely ((in_flags & MSG_WAITALL) && !(in_flags & MSG_PEEK))) {
1936- total_iov_sz = 0 ;
1937- for (int i = 0 ; i < sz_iov; i++) {
1938- total_iov_sz += p_iov[i].iov_len ;
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+ if (unlikely ((in_flags & MSG_WAITALL) && !(in_flags & MSG_PEEK))) {
1946+ total_iov_sz = 0 ;
1947+ for (int i = 0 ; i < sz_iov; i++) {
1948+ total_iov_sz += p_iov[i].iov_len ;
1949+ }
1950+ if (total_iov_sz == 0 )
1951+ return 0 ;
19391952 }
1940- if (total_iov_sz == 0 )
1941- return 0 ;
19421953 }
19431954
19441955 si_tcp_logfunc (" rx: iov=%p niovs=%d" , p_iov, sz_iov);
1945- /* poll rx queue till we have something */
1956+
1957+ /* poll rx queue till we have something */
19461958 lock_tcp_con ();
1959+ if (__msg) {
1960+ handle_cmsg (__msg, in_flags);
1961+ if (__msg->msg_controllen == 0 ) {
1962+ errno = EAGAIN;
1963+ unlock_tcp_con ();
1964+ return -1 ;
1965+ }
1966+ }
19471967 return_reuse_buffers_postponed ();
19481968 unlock_tcp_con ();
19491969
19501970 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 ))) {
1971+ if (unlikely (g_b_exit || !is_rtr () || (rx_wait_lockless (poll_count, block_this_run) < 0 ))) {
19521972 return handle_rx_error (block_this_run);
19531973 }
19541974 }
@@ -1957,8 +1977,9 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec* p_iov, ssize_t sz_iov
19571977
19581978 si_tcp_logfunc (" something in rx queues: %d %p" , m_n_rx_pkt_ready_list_count, m_rx_pkt_ready_list.front ());
19591979
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);
1980+ if (total_iov_sz > 0 ) {
1981+ total_rx = dequeue_packet (p_iov, sz_iov, (sockaddr_in *)__from, __fromlen, in_flags, &out_flags);
1982+ }
19621983
19631984 /*
19641985 * RCVBUFF Accounting: Going 'out' of the internal buffer: if some bytes are not tcp_recved yet - do that.
0 commit comments