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);

Reply via email to