mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 09:10:28 +00:00
sockets: repair wakeup of accept(2) by shutdown(2)
That was lost in transition from one-for-all soshutdown() to protocol
specific methods. Only protocols that listen(2) were affected. This is
not a documented or specified feature, but some software relies on it. At
least the FreeSWITCH telephony software uses this behavior on
PF_INET/SOCK_STREAM.
Fixes: 5bba272807
This commit is contained in:
parent
2c5ff9118c
commit
abe8379b4f
|
@ -1669,7 +1669,14 @@ uipc_shutdown(struct socket *so, enum shutdown_how how)
|
|||
int error;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state &
|
||||
if (SOLISTENING(so)) {
|
||||
if (how != SHUT_WR) {
|
||||
so->so_error = ECONNABORTED;
|
||||
solisten_wakeup(so); /* unlocks so */
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOTCONN);
|
||||
} else if ((so->so_state &
|
||||
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
|
||||
/*
|
||||
* POSIX mandates us to just return ENOTCONN when shutdown(2) is
|
||||
|
@ -1691,14 +1698,6 @@ uipc_shutdown(struct socket *so, enum shutdown_how how)
|
|||
}
|
||||
} else
|
||||
error = 0;
|
||||
if (SOLISTENING(so)) {
|
||||
if (how != SHUT_WR) {
|
||||
so->so_error = ECONNABORTED;
|
||||
solisten_wakeup(so); /* unlocks so */
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
switch (how) {
|
||||
|
|
|
@ -794,18 +794,17 @@ sctp_shutdown(struct socket *so, enum shutdown_how how)
|
|||
return (EOPNOTSUPP);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state &
|
||||
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
if (SOLISTENING(so)) {
|
||||
if (how != SHUT_WR) {
|
||||
so->so_error = ECONNABORTED;
|
||||
solisten_wakeup(so); /* unlocks so */
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
return (ENOTCONN);
|
||||
} else if ((so->so_state &
|
||||
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
|
|
|
@ -807,18 +807,17 @@ tcp_usr_shutdown(struct socket *so, enum shutdown_how how)
|
|||
int error = 0;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state &
|
||||
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
if (SOLISTENING(so)) {
|
||||
if (how != SHUT_WR) {
|
||||
so->so_error = ECONNABORTED;
|
||||
solisten_wakeup(so); /* unlocks so */
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
return (ENOTCONN);
|
||||
} else if ((so->so_state &
|
||||
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
|
|
Loading…
Reference in a new issue