Re: SCTP doesn't seem to let you 'cancel' a blocking accept()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jun 3, 2024 at 11:42 AM David Laight <David.Laight@xxxxxxxxxx> wrote:
>
> In a multithreaded program it is reasonable to have a thread blocked in accept().
> With TCP a subsequent shutdown(listen_fd, SHUT_RDWR) causes the accept to fail.
> But nothing happens for SCTP.
>
> I think the 'magic' happens when tcp_disconnect() calls inet_csk_listen_stop(sk)
> but sctp_disconnect() is an empty function and nothing happens.
>
> I can't see any calls to inet_csk_listen_stop() in the sctp code - so I suspect
> it isn't possible at all.
I guess SCTP doesn't take action due to the description
in rfc6458#section-4.1.7:

      SHUT_RD:  Disables further receive operations.  No SCTP protocol
         action is taken.

>
> This all relates to a very old (pre git) comment in inet_shutdown() that
> shutdown needs to act on listening and connecting sockets until the VFS
> layer is 'fixed' (presumably to let close() through - not going to happen.)
didn't know that, it's better to have it on some standard doc.

>
> I also suspect that a blocking connect() can't be cancelled either?
For connecting socket, it calls sctp_shutdown() where SHUT_WR causes
the asoc to enter SHUTDOWN_SENT and cancel the blocking connect().

>
> Clearly the application can avoid the issue by using poll() and an
> extra eventfd() for the wakeup - but it is all a faff for code that
> otherwise straight forward.
I will try to prepare a patch to solve this for sctp accept() like:

diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c67679a41044..f270a0a4c65d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4834,10 +4834,13 @@ int sctp_inet_connect(struct socket *sock,
struct sockaddr *uaddr,
        return sctp_connect(sock->sk, uaddr, addr_len, flags);
 }

-/* FIXME: Write comments. */
 static int sctp_disconnect(struct sock *sk, int flags)
 {
-       return -EOPNOTSUPP; /* STUB */
+       if (!sctp_style(sk, TCP))
+               return -EOPNOTSUPP;
+
+       sk->sk_shutdown |= RCV_SHUTDOWN;
+       return 0;
 }

 /* 4.1.4 accept() - TCP Style Syntax
@@ -4866,7 +4869,7 @@ static struct sock *sctp_accept(struct sock *sk,
int flags, int *err, bool kern)
                goto out;
        }

-       if (!sctp_sstate(sk, LISTENING)) {
+       if (!sctp_sstate(sk, LISTENING) || (sk->sk_shutdown & RCV_SHUTDOWN)) {
                error = -EINVAL;
                goto out;
        }
@@ -9392,7 +9395,7 @@ static int sctp_wait_for_accept(struct sock *sk,
long timeo)
                }

                err = -EINVAL;
-               if (!sctp_sstate(sk, LISTENING))
+               if (!sctp_sstate(sk, LISTENING) || (sk->sk_shutdown &
RCV_SHUTDOWN))
                        break;

                err = 0;

Thanks.





[Index of Archives]     [Linux Networking Development]     [Linux OMAP]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     SCTP

  Powered by Linux