Date: Thu, 8 Jun 2017 06:16:47 +0000 (UTC) From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r319685 - head/sys/kern Message-ID: <201706080616.v586Glh8020211@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: glebius Date: Thu Jun 8 06:16:47 2017 New Revision: 319685 URL: https://svnweb.freebsd.org/changeset/base/319685 Log: Fix a degenerate case when soisdisconnected() would call soisconnected(). This happens when closing a socket with upcall, and trace is: soclose()-> ... protocol ... -> soisdisconnected() -> socantrcvmore_locked() -> sowakeup() -> soisconnected(). Right now this case is innocent for two reasons. First, soisconnected() doesn't clear SS_ISDISCONNECTED flag. Second, the mutex to lock the socket is the socket receive buffer mutex, and sodisconnected() first disables the receive buffer. But in future code, the mutex to lock socket is different to buffer mutex, and we would get undesired mutex recursion. The fix is to check SS_ISDISCONNECTED flag before calling upcall. Modified: head/sys/kern/uipc_sockbuf.c Modified: head/sys/kern/uipc_sockbuf.c ============================================================================== --- head/sys/kern/uipc_sockbuf.c Thu Jun 8 06:13:53 2017 (r319684) +++ head/sys/kern/uipc_sockbuf.c Thu Jun 8 06:16:47 2017 (r319685) @@ -322,7 +322,7 @@ sowakeup(struct socket *so, struct sockbuf *sb) wakeup(&sb->sb_acc); } KNOTE_LOCKED(&sb->sb_sel.si_note, 0); - if (sb->sb_upcall != NULL) { + if (sb->sb_upcall != NULL && !(so->so_state & SS_ISDISCONNECTED)) { ret = sb->sb_upcall(so, sb->sb_upcallarg, M_NOWAIT); if (ret == SU_ISCONNECTED) { KASSERT(sb == &so->so_rcv,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706080616.v586Glh8020211>