diff --git a/sys/bus/u4b/usb_dev.c b/sys/bus/u4b/usb_dev.c --- a/sys/bus/u4b/usb_dev.c +++ b/sys/bus/u4b/usb_dev.c @@ -798,6 +798,7 @@ if (f->async_p != NULL && lwkt_trytoken(&f->async_p->p_token)) { ksignal(f->async_p, SIGIO); lwkt_reltoken(&f->async_p->p_token); + PRELE(f->async_p); f->async_p = NULL; } /* remove FWRITE and FREAD flags */ @@ -1037,13 +1038,22 @@ case FIOASYNC: if (*(int *)addr) { + struct proc *p; if (f->async_p != NULL) { error = EBUSY; break; } - f->async_p = USB_TD_GET_PROC(td); + /* Take a reference so the proc cannot be reaped while a + * FIFO still async-signals it (defense-in-depth until USB + * adopts the refcounted struct sigio mechanism). */ + p = USB_TD_GET_PROC(td); + PHOLD(p); + f->async_p = p; } else { + struct proc *p = f->async_p; f->async_p = NULL; + if (p != NULL) + PRELE(p); } break;