On Tue, Oct 26, 2021 at 02:12:36PM +0300, Vitaliy Makkoveev wrote:
> --- sys/kern/uipc_socket.c    14 Oct 2021 23:05:10 -0000      1.265
> +++ sys/kern/uipc_socket.c    26 Oct 2021 11:05:59 -0000
> @@ -315,6 +315,8 @@ soclose(struct socket *so, int flags)
>       /* Revoke async IO early. There is a final revocation in sofree(). */
>       sigio_free(&so->so_sigio);
>       if (so->so_options & SO_ACCEPTCONN) {
> +             so->so_options &= ~SO_ACCEPTCONN;
> +
>               while ((so2 = TAILQ_FIRST(&so->so_q0)) != NULL) {
>                       (void) soqremque(so2, 0);
>                       (void) soabort(so2);

I don't like this.  A listening socket can never be converted to a
non-listening socket.  Whatever this transition means in th TCP
layer.  If you want to mark a listening socket as closing to avoid
accepting connections, use a approriate flag.  Do not convert it
to an non-listening socket that may have races elsewhere.

I would say some so_state bits may be suitable if we really need
this feature.

> -     if (unp->unp_vnode) {
> +
> +     if (vp) {

Please use (vp != NULL) for consistency.

> +             unp->unp_vnode = NULL;
> +
>               /*
> -              * `v_socket' is only read in unp_connect and
> -              * unplock prevents concurrent access.
> +              * Enforce `i_lock' -> `unp_lock' because fifo
> +              * subsystem requires it.
>                */
>  
> -             unp->unp_vnode->v_socket = NULL;
> -             vp = unp->unp_vnode;
> -             unp->unp_vnode = NULL;
> +             sounlock(so, SL_LOCKED);
> +
> +             VOP_LOCK(vp, LK_EXCLUSIVE);
> +             vp->v_socket = NULL;
> +
> +             KERNEL_LOCK();
> +             vput(vp);
> +             KERNEL_UNLOCK();
> +
> +             solock(so);
>       }

This might work, we should try it.

> @@ -500,21 +510,6 @@ unp_detach(struct unpcb *unp)
>       pool_put(&unpcb_pool, unp);
>       if (unp_rights)
>               task_add(systqmp, &unp_gc_task);
> -
> -     if (vp != NULL) {
> -             /*
> -              * Enforce `i_lock' -> `unplock' because fifo subsystem
> -              * requires it. The socket can't be closed concurrently
> -              * because the file descriptor reference is
> -              * still hold.
> -              */
> -
> -             sounlock(so, SL_LOCKED);
> -             KERNEL_LOCK();
> -             vrele(vp);
> -             KERNEL_UNLOCK();
> -             solock(so);
> -     }
>  }

Why did you move the lock dance to the beginning of the function?
Does it matter?

bluhm

Reply via email to