lio_listio(2): send signal even if number of jobs is zero.

Right now, if lio registered zero jobs, syscall frees lio job
structure, cleaning up queued ksi.  As result, the realtime signal is
dequeued and never delivered.

Fix it by allowing sendsig() to copy ksi when job count is zero.

PR: 220398
Reported and reviewed by:	asomers
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D27421
This commit is contained in:
Konstantin Belousov 2020-12-01 22:53:33 +00:00
parent 2933165666
commit 6814c2dac5

View File

@ -466,7 +466,7 @@ aio_init_aioinfo(struct proc *p)
}
static int
aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi)
aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi, bool ext)
{
struct thread *td;
int error;
@ -477,7 +477,7 @@ aio_sendsig(struct proc *p, struct sigevent *sigev, ksiginfo_t *ksi)
if (!KSI_ONQ(ksi)) {
ksiginfo_set_sigev(ksi, sigev);
ksi->ksi_code = SI_ASYNCIO;
ksi->ksi_flags |= KSI_EXT | KSI_INS;
ksi->ksi_flags |= ext ? (KSI_EXT | KSI_INS) : 0;
tdsendsignal(p, td, ksi->ksi_signo, ksi);
}
PROC_UNLOCK(p);
@ -896,7 +896,7 @@ aio_bio_done_notify(struct proc *userp, struct kaiocb *job)
if (job->uaiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL ||
job->uaiocb.aio_sigevent.sigev_notify == SIGEV_THREAD_ID)
aio_sendsig(userp, &job->uaiocb.aio_sigevent, &job->ksi);
aio_sendsig(userp, &job->uaiocb.aio_sigevent, &job->ksi, true);
KNOTE_LOCKED(&job->klist, 1);
@ -909,7 +909,8 @@ aio_bio_done_notify(struct proc *userp, struct kaiocb *job)
== LIOJ_SIGNAL &&
(lj->lioj_signal.sigev_notify == SIGEV_SIGNAL ||
lj->lioj_signal.sigev_notify == SIGEV_THREAD_ID)) {
aio_sendsig(userp, &lj->lioj_signal, &lj->lioj_ksi);
aio_sendsig(userp, &lj->lioj_signal, &lj->lioj_ksi,
true);
lj->lioj_flags |= LIOJ_SIGNAL_POSTED;
}
}
@ -2238,7 +2239,8 @@ kern_lio_listio(struct thread *td, int mode, struct aiocb * const *uacb_list,
LIOJ_SIGNAL_POSTED)) == LIOJ_SIGNAL &&
(lj->lioj_signal.sigev_notify == SIGEV_SIGNAL ||
lj->lioj_signal.sigev_notify == SIGEV_THREAD_ID)) {
aio_sendsig(p, &lj->lioj_signal, &lj->lioj_ksi);
aio_sendsig(p, &lj->lioj_signal, &lj->lioj_ksi,
lj->lioj_count != 1);
lj->lioj_flags |= LIOJ_SIGNAL_POSTED;
}
}