Index: if_tapvar.h =================================================================== --- if_tapvar.h (revision 240942) +++ if_tapvar.h (working copy) @@ -54,6 +54,7 @@ #define TAP_ASYNC (1 << 3) #define TAP_READY (TAP_OPEN|TAP_INITED) #define TAP_VMNET (1 << 4) +#define TAP_GONE (1 << 5) u_int8_t ether_addr[ETHER_ADDR_LEN]; /* ether addr of the remote side */ Index: if_tap.c =================================================================== --- if_tap.c (revision 240941) +++ if_tap.c (working copy) @@ -209,11 +209,36 @@ } static void +tap_wakeup(struct tap_softc *tp) +{ + + if (tp->tap_flags & TAP_RWAIT) { + tp->tap_flags &= ~TAP_RWAIT; + wakeup(tp); + } + + if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) { + mtx_unlock(&tp->tap_mtx); + pgsigio(&tp->tap_sigio, SIGIO, 0); + mtx_lock(&tp->tap_mtx); + } + + selwakeuppri(&tp->tap_rsel, PZERO+1); + KNOTE_LOCKED(&tp->tap_rsel.si_note, 0); +} + +static void tap_destroy(struct tap_softc *tp) { struct ifnet *ifp = tp->tap_ifp; CURVNET_SET(ifp->if_vnet); + mtx_lock(&tp->tap_mtx); + if ((tp->tap_flags & TAP_OPEN) != 0) { + tp->tap_flags |= TAP_GONE; + tap_wakeup(tp); + } + mtx_unlock(&tp->tap_mtx); destroy_dev(tp->tap_dev); seldrain(&tp->tap_rsel); knlist_destroy(&tp->tap_rsel.si_note); @@ -690,19 +715,7 @@ ifp->if_drv_flags |= IFF_DRV_OACTIVE; if (!IFQ_IS_EMPTY(&ifp->if_snd)) { - if (tp->tap_flags & TAP_RWAIT) { - tp->tap_flags &= ~TAP_RWAIT; - wakeup(tp); - } - - if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) { - mtx_unlock(&tp->tap_mtx); - pgsigio(&tp->tap_sigio, SIGIO, 0); - mtx_lock(&tp->tap_mtx); - } - - selwakeuppri(&tp->tap_rsel, PZERO+1); - KNOTE_LOCKED(&tp->tap_rsel.si_note, 0); + tap_wakeup(tp); ifp->if_opackets ++; /* obytes are counted in ether_output */ } @@ -885,7 +898,7 @@ tp->tap_flags |= TAP_RWAIT; error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1), "taprd", 0); - if (error) { + if (error || (tp->tap_flags & TAP_GONE) != 0) { mtx_unlock(&tp->tap_mtx); return (error); } @@ -929,7 +942,7 @@ struct ifnet *ifp = tp->tap_ifp; struct mbuf *m; - TAPDEBUG("%s writting, minor = %#x\n", + TAPDEBUG("%s writing, minor = %#x\n", ifp->if_xname, dev2unit(dev)); if (uio->uio_resid == 0) @@ -1011,7 +1024,9 @@ IFQ_UNLOCK(&ifp->if_snd); } - if (events & (POLLOUT | POLLWRNORM)) + if ((tp->tap_flags & TAP_GONE) != 0) + revents |= POLLHUP; + else if (events & (POLLOUT | POLLWRNORM)) revents |= (events & (POLLOUT | POLLWRNORM)); return (revents); @@ -1069,7 +1084,10 @@ struct cdev *dev = tp->tap_dev; struct ifnet *ifp = tp->tap_ifp; - if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { + if ((tp->tap_flags & TAP_GONE) != 0) { + kn->kn_flags |= EV_EOF; + ret = 1; + } else if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n", ifp->if_xname, ifp->if_snd.ifq_len, dev2unit(dev)); ret = 1; @@ -1094,7 +1112,10 @@ struct tap_softc *tp = kn->kn_hook; struct ifnet *ifp = tp->tap_ifp; - kn->kn_data = ifp->if_mtu; + if ((tp->tap_flags & TAP_GONE) != 0) + kn->kn_flags |= EV_EOF; + else + kn->kn_data = ifp->if_mtu; return (1); } /* tapkqwrite */