On Thu, Jan 19, 2017 at 07:14:59PM +1000, Martin Pieuchot wrote:
> Index: kern/uipc_syscalls.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
> retrieving revision 1.144
> diff -u -p -r1.144 uipc_syscalls.c
> --- kern/uipc_syscalls.c 29 Dec 2016 12:12:43 -0000 1.144
> +++ kern/uipc_syscalls.c 19 Jan 2017 09:03:56 -0000
> @@ -278,6 +278,7 @@ doaccept(struct proc *p, int sock, struc
>
> headfp = fp;
> redo:
> + fdplock(fdp);
> NET_LOCK(s);
> head = headfp->f_data;
> if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) {
...
There we have
error = rwsleep(&head->so_timeo, &netlock, PSOCK | PCATCH,
"netcon", 0);
You release the netlock during sleep but still hold the fdplock.
This leads to a deadlock of userland during
/usr/src/regress/lib/libpthread/socket/1.
277134 socket1 native 0xffff800003accfd8 thrsleep
236121 socket1 native 0xffffff00023eab56 netcon
220469 socket1 native 0xffffff0004d53a98 fdlock
ddb{0}> trace /p 0t236121
sleep_finish() at sleep_finish+0xb1
rwsleep() at rwsleep+0x8e
doaccept() at doaccept+0x37b
syscall() at syscall+0x27b
--- syscall (number 30) ---
ddb{0}> trace /p 0t220469
sleep_finish() at sleep_finish+0xb1
rw_enter() at rw_enter+0x1cb
sys_socket() at sys_socket+0xbf
syscall() at syscall+0x27b
--- syscall (number 97) ---
> @@ -312,11 +313,9 @@ redo:
> nflag = flags & SOCK_NONBLOCK_INHERIT ? (headfp->f_flag & FNONBLOCK)
> : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0);
>
> - fdplock(fdp);
> error = falloc(p, &fp, &tmpfd);
> if (error == 0 && (flags & SOCK_CLOEXEC))
> fdp->fd_ofileflags[tmpfd] |= UF_EXCLOSE;
> - fdpunlock(fdp);
> if (error != 0) {
> /*
> * Probably ran out of file descriptors. Wakeup
> @@ -336,7 +335,6 @@ redo:
> if (head->so_qlen == 0) {
> NET_UNLOCK(s);
> m_freem(nam);
> - fdplock(fdp);
> fdremove(fdp, tmpfd);
> closef(fp, p);
> fdpunlock(fdp);
> @@ -365,7 +363,6 @@ redo:
> /* if an error occurred, free the file descriptor */
> NET_UNLOCK(s);
> m_freem(nam);
> - fdplock(fdp);
> fdremove(fdp, tmpfd);
> closef(fp, p);
> fdpunlock(fdp);
> @@ -377,6 +374,7 @@ redo:
> m_freem(nam);
> bad:
> NET_UNLOCK(s);
> + fdpunlock(fdp);
> out:
> FRELE(headfp, p);
> return (error);