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.