Sometimes, when doing read(2) over unix domain socket, for which the other side socket was closed, read(2) returns -1/ENOTCONN instead of EOF AKA zero-size read. This is because soreceive_generic does not lock socket when testing the so_state SS_ISCONNECTED|SS_ISCONNECTING flags. It could end up that we do not observe so->so_rcv.sb_state bit SBS_CANTRCVMORE, and then miss SS_ flags.
Reverting the order of checks for SBS and SS would not help, I believe this would result in different problem, that we enter sbwait() too late, missing wakeups soisdisconnected(). Also, I think it is not desirable to add socket locking to soreceive_generic(), because socket read is a hot path, while soisdisconnected() is not so hot.
I propose the following fix for discussion. Its main uncertainty point is that I have to establish order between socket lock and sockbuf locks. I do not quite understand the note in r322856 about recursion.
Problem was reported by pho, and the patch is confirmed to fix the issue. Also it survived all stress2 socket tests.