diff mbox series

[net] udp: call sock_def_readable() if socket is not SOCK_FASYNC

Message ID 20241126175402.1506-1-ffmancera@riseup.net (mailing list archive)
State New
Delegated to: Netdev Maintainers
Headers show
Series [net] udp: call sock_def_readable() if socket is not SOCK_FASYNC | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 3 this patch: 3
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers fail 2 blamed authors not CCed: kuba@kernel.org pabeni@redhat.com; 4 maintainers not CCed: kuba@kernel.org horms@kernel.org pabeni@redhat.com dsahern@kernel.org
netdev/build_clang success Errors and warnings before: 3 this patch: 3
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 10 this patch: 10
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 7 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 3 this patch: 3
netdev/source_inline success Was 0 now: 0

Commit Message

Fernando F. Mancera Nov. 26, 2024, 5:53 p.m. UTC
If a socket is not SOCK_FASYNC, sock_def_readable() needs to be called
even if receive queue was not empty. Otherwise, if several threads are
listening on the same socket with blocking recvfrom() calls they might
hang waiting for data to be received.

Link: https://bugzilla.redhat.com/2308477
Fixes: 612b1c0dec5b ("udp: avoid calling sock_def_readable() if possible")
Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
---
 net/ipv4/udp.c | 1 +
 1 file changed, 1 insertion(+)

Comments

Eric Dumazet Nov. 26, 2024, 6:32 p.m. UTC | #1
On Tue, Nov 26, 2024 at 6:56 PM Fernando Fernandez Mancera
<ffmancera@riseup.net> wrote:
>
> If a socket is not SOCK_FASYNC, sock_def_readable() needs to be called
> even if receive queue was not empty. Otherwise, if several threads are
> listening on the same socket with blocking recvfrom() calls they might
> hang waiting for data to be received.
>

SOCK_FASYNC seems completely orthogonal to the issue.

First sock_def_readable() should wakeup all threads, I wonder what is happening.

UDP can store incoming packets into sk->sk_receive_queue and
udp_sk(sk)->reader_queue

Paolo, should __skb_wait_for_more_packets() for UDP socket look at both queues ?
Eric Dumazet Nov. 26, 2024, 6:41 p.m. UTC | #2
On Tue, Nov 26, 2024 at 7:32 PM Eric Dumazet <edumazet@google.com> wrote:
>
> On Tue, Nov 26, 2024 at 6:56 PM Fernando Fernandez Mancera
> <ffmancera@riseup.net> wrote:
> >
> > If a socket is not SOCK_FASYNC, sock_def_readable() needs to be called
> > even if receive queue was not empty. Otherwise, if several threads are
> > listening on the same socket with blocking recvfrom() calls they might
> > hang waiting for data to be received.
> >
>
> SOCK_FASYNC seems completely orthogonal to the issue.
>
> First sock_def_readable() should wakeup all threads, I wonder what is happening.

Oh well, __skb_wait_for_more_packets() is using
prepare_to_wait_exclusive(), so in this case sock_def_readable() is
waking only one thread.

>
> UDP can store incoming packets into sk->sk_receive_queue and
> udp_sk(sk)->reader_queue
>
> Paolo, should __skb_wait_for_more_packets() for UDP socket look at both queues ?
Fernando F. Mancera Nov. 26, 2024, 7:17 p.m. UTC | #3
Hi,

On 26/11/2024 19:41, Eric Dumazet wrote:
> On Tue, Nov 26, 2024 at 7:32 PM Eric Dumazet <edumazet@google.com> wrote:
>>
>> On Tue, Nov 26, 2024 at 6:56 PM Fernando Fernandez Mancera
>> <ffmancera@riseup.net> wrote:
>>>
>>> If a socket is not SOCK_FASYNC, sock_def_readable() needs to be called
>>> even if receive queue was not empty. Otherwise, if several threads are
>>> listening on the same socket with blocking recvfrom() calls they might
>>> hang waiting for data to be received.
>>>
>>
>> SOCK_FASYNC seems completely orthogonal to the issue.
>>
>> First sock_def_readable() should wakeup all threads, I wonder what is happening.
> 

Well, it might be. But I noticed that if SOCK_FASYNC is set then 
sk_wake_async_rcu() do its work and everything is fine. This is why I 
thought checking on the flag was a good idea.

> Oh well, __skb_wait_for_more_packets() is using
> prepare_to_wait_exclusive(), so in this case sock_def_readable() is
> waking only one thread.
> 

Yes, this is what I was expecting. What would be the solution? Should I 
change it to "prepare_to_wait()" instead? Although, I don't know the 
implication that change might have.

Thank you for the comments, first time working on UDP socket 
implementation so they are very helpful :)

>>
>> UDP can store incoming packets into sk->sk_receive_queue and
>> udp_sk(sk)->reader_queue
>>
>> Paolo, should __skb_wait_for_more_packets() for UDP socket look at both queues ?
Eric Dumazet Nov. 26, 2024, 7:26 p.m. UTC | #4
On Tue, Nov 26, 2024 at 8:18 PM Fernando F. Mancera
<ffmancera@riseup.net> wrote:
>
> Hi,
>
> On 26/11/2024 19:41, Eric Dumazet wrote:
> > On Tue, Nov 26, 2024 at 7:32 PM Eric Dumazet <edumazet@google.com> wrote:
> >>
> >> On Tue, Nov 26, 2024 at 6:56 PM Fernando Fernandez Mancera
> >> <ffmancera@riseup.net> wrote:
> >>>
> >>> If a socket is not SOCK_FASYNC, sock_def_readable() needs to be called
> >>> even if receive queue was not empty. Otherwise, if several threads are
> >>> listening on the same socket with blocking recvfrom() calls they might
> >>> hang waiting for data to be received.
> >>>
> >>
> >> SOCK_FASYNC seems completely orthogonal to the issue.
> >>
> >> First sock_def_readable() should wakeup all threads, I wonder what is happening.
> >
>
> Well, it might be. But I noticed that if SOCK_FASYNC is set then
> sk_wake_async_rcu() do its work and everything is fine. This is why I
> thought checking on the flag was a good idea.
>

How have you tested SOCK_FASYNC ?

SOCK_FASYNC is sending signals. If SIGIO is blocked, I am pretty sure
the bug is back.


> > Oh well, __skb_wait_for_more_packets() is using
> > prepare_to_wait_exclusive(), so in this case sock_def_readable() is
> > waking only one thread.
> >
>
> Yes, this is what I was expecting. What would be the solution? Should I
> change it to "prepare_to_wait()" instead? Although, I don't know the
> implication that change might have.

Sadly, we will have to revert, this exclusive wake is subtle.
Fernando F. Mancera Nov. 26, 2024, 7:30 p.m. UTC | #5
On 26/11/2024 20:26, Eric Dumazet wrote:
> On Tue, Nov 26, 2024 at 8:18 PM Fernando F. Mancera
> <ffmancera@riseup.net> wrote:
>>
>> Hi,
>>
>> On 26/11/2024 19:41, Eric Dumazet wrote:
>>> On Tue, Nov 26, 2024 at 7:32 PM Eric Dumazet <edumazet@google.com> wrote:
>>>>
>>>> On Tue, Nov 26, 2024 at 6:56 PM Fernando Fernandez Mancera
>>>> <ffmancera@riseup.net> wrote:
>>>>>
>>>>> If a socket is not SOCK_FASYNC, sock_def_readable() needs to be called
>>>>> even if receive queue was not empty. Otherwise, if several threads are
>>>>> listening on the same socket with blocking recvfrom() calls they might
>>>>> hang waiting for data to be received.
>>>>>
>>>>
>>>> SOCK_FASYNC seems completely orthogonal to the issue.
>>>>
>>>> First sock_def_readable() should wakeup all threads, I wonder what is happening.
>>>
>>
>> Well, it might be. But I noticed that if SOCK_FASYNC is set then
>> sk_wake_async_rcu() do its work and everything is fine. This is why I
>> thought checking on the flag was a good idea.
>>
> 
> How have you tested SOCK_FASYNC ?
> 
> SOCK_FASYNC is sending signals. If SIGIO is blocked, I am pretty sure
> the bug is back.
> 

Ah, I didn't know SIGIO was going to be blocked.

> 
>>> Oh well, __skb_wait_for_more_packets() is using
>>> prepare_to_wait_exclusive(), so in this case sock_def_readable() is
>>> waking only one thread.
>>>
>>
>> Yes, this is what I was expecting. What would be the solution? Should I
>> change it to "prepare_to_wait()" instead? Although, I don't know the
>> implication that change might have.
> 
> Sadly, we will have to revert, this exclusive wake is subtle.

If that is the case, let me send a revert patch. Thanks for the fast 
replies :)
Eric Dumazet Nov. 26, 2024, 7:33 p.m. UTC | #6
On Tue, Nov 26, 2024 at 8:30 PM Fernando F. Mancera
<ffmancera@riseup.net> wrote:
>
>
>
> On 26/11/2024 20:26, Eric Dumazet wrote:
> > On Tue, Nov 26, 2024 at 8:18 PM Fernando F. Mancera
> > <ffmancera@riseup.net> wrote:
> >>
> >> Hi,
> >>
> >> On 26/11/2024 19:41, Eric Dumazet wrote:
> >>> On Tue, Nov 26, 2024 at 7:32 PM Eric Dumazet <edumazet@google.com> wrote:
> >>>>
> >>>> On Tue, Nov 26, 2024 at 6:56 PM Fernando Fernandez Mancera
> >>>> <ffmancera@riseup.net> wrote:
> >>>>>
> >>>>> If a socket is not SOCK_FASYNC, sock_def_readable() needs to be called
> >>>>> even if receive queue was not empty. Otherwise, if several threads are
> >>>>> listening on the same socket with blocking recvfrom() calls they might
> >>>>> hang waiting for data to be received.
> >>>>>
> >>>>
> >>>> SOCK_FASYNC seems completely orthogonal to the issue.
> >>>>
> >>>> First sock_def_readable() should wakeup all threads, I wonder what is happening.
> >>>
> >>
> >> Well, it might be. But I noticed that if SOCK_FASYNC is set then
> >> sk_wake_async_rcu() do its work and everything is fine. This is why I
> >> thought checking on the flag was a good idea.
> >>
> >
> > How have you tested SOCK_FASYNC ?
> >
> > SOCK_FASYNC is sending signals. If SIGIO is blocked, I am pretty sure
> > the bug is back.
> >
>
> Ah, I didn't know SIGIO was going to be blocked.
>
> >
> >>> Oh well, __skb_wait_for_more_packets() is using
> >>> prepare_to_wait_exclusive(), so in this case sock_def_readable() is
> >>> waking only one thread.
> >>>
> >>
> >> Yes, this is what I was expecting. What would be the solution? Should I
> >> change it to "prepare_to_wait()" instead? Although, I don't know the
> >> implication that change might have.
> >
> > Sadly, we will have to revert, this exclusive wake is subtle.
>
> If that is the case, let me send a revert patch. Thanks for the fast
> replies :)

Please wait one day before sending a new patch, thanks.
diff mbox series

Patch

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 6a01905d379f..4c398e6945ee 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1722,6 +1722,7 @@  int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
 	if (!sock_flag(sk, SOCK_DEAD)) {
 		if (becomes_readable ||
 		    sk->sk_data_ready != sock_def_readable ||
+		    !sock_flag(sk, SOCK_FASYNC) ||
 		    READ_ONCE(sk->sk_peek_off) >= 0)
 			INDIRECT_CALL_1(sk->sk_data_ready,
 					sock_def_readable, sk);