DF-2778 / fix.diff
Fix for DF-2778: clear mq_notify registrations at process exit (mqueue_proc_exit). --- sys_mqueue.c 2026-09-01 04:01:55.500648734 +0000 +++ sys_mqueue.2778.only 2026-09-01 04:03:50.167194127 +0000 @@ -408,6 +408,29 @@ } /* + * mqueue_proc_exit: called from exit1() after the exiting process's + * descriptors have been closed. mq_close_fop() only runs when the LAST + * file reference drops, which may happen in a different process (fork) + * long after the registrant exited; clear any notification registrations + * that still point at the exiting process so mq_notify_proc can never + * dangle. + */ +void +mqueue_proc_exit(struct proc *p) +{ + struct mqueue *mq; + + lockmgr(&mqlist_mtx, LK_EXCLUSIVE); + LIST_FOREACH(mq, &mqueue_head, mq_list) { + lockmgr(&mq->mq_mtx, LK_EXCLUSIVE); + if (mq->mq_notify_proc == p) + mq->mq_notify_proc = NULL; + lockmgr(&mq->mq_mtx, LK_RELEASE); + } + lockmgr(&mqlist_mtx, LK_RELEASE); +} + +/* * General mqueue system calls. */ --- kern_exit.c 2026-09-01 04:01:55.500648734 +0000 +++ kern_exit.c.new 2026-09-01 04:02:22.424307123 +0000 @@ -381,6 +381,13 @@ */ fdfree(p, NULL); + /* + * Clear POSIX mqueue notification registrations still targeting + * this process (the registrant may have exited while a fork child + * still holds the descriptor). + */ + mqueue_proc_exit(p); + if (p->p_leader->p_peers) { q = p->p_leader; while(q->p_peers != p) --- mqueue.h 2026-09-01 04:01:55.504648683 +0000 +++ mqueue.h.new 2026-09-01 04:02:22.428307072 +0000 @@ -117,6 +117,7 @@ /* Prototypes */ void mqueue_sysinit(void); +void mqueue_proc_exit(struct proc *); int abstimeout2timo(struct timespec *, int *); int mq_send1(struct lwp *, mqd_t, const char *, size_t, unsigned, struct timespec *); int mq_receive1(struct lwp *, mqd_t, void *, size_t, unsigned *, struct timespec *, |