| Summary: | signal is not posted for async I/O on raw devices | ||
|---|---|---|---|
| Product: | Base System | Reporter: | kwchen <kwchen> |
| Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 3.2-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
Here's a patch that should fix the problem. Warning: this patch comes from
my own version of vfs_aio.c (no differences exist between my code and the
code modified below, except that which is expressed below, so no
incompatibilities should arise). This may cause problems because line
offsets are significantly different, and I had to hand edit the last patch
chunk to eliminate a bunch of followon stuff.
*************** lio_listio(struct proc *p, struct lio_li
*** 1930,1944 ****
* to do so from a timeout routine, but *not* from an interrupt routine.
*/
static void
! process_signal(void *ljarg)
{
! struct aio_liojob *lj = ljarg;
! if (lj->lioj_signal.sigev_notify == SIGEV_SIGNAL) {
! if (lj->lioj_queue_count == lj->lioj_queue_finished_count) {
! psignal(lj->lioj_ki->kaio_p,
lj->lioj_signal.sigev_signo);
! lj->lioj_flags |= LIOJ_SIGNAL_POSTED;
}
}
}
/*
--- 2062,2086 ----
* to do so from a timeout routine, but *not* from an interrupt routine.
*/
static void
! process_signal(void *aioj)
{
! struct aiocblist *aiocbe = aioj;
! struct aio_liojob *lj = aiocbe->lio;
! struct aiocb *cb = &aiocbe->uaiocb;
!
! if (lj) {
! if (lj->lioj_signal.sigev_notify == SIGEV_SIGNAL) {
! if (lj->lioj_queue_count ==
lj->lioj_queue_finished_count) {
! psignal(lj->lioj_ki->kaio_p,
lj->lioj_signal.sigev_signo);
! lj->lioj_flags |= LIOJ_SIGNAL_POSTED;
! }
}
}
+
+ if (cb->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
+ psignal(aiocbe->userproc,cb->aio_sigevent.sigev_signo);
+ }
+
}
/*
*************** aio_physwakeup(bp)
*** 1986,1992 ****
if ((lj->lioj_flags &
(LIOJ_SIGNAL|LIOJ_SIGNAL_POSTED)) ==
LIOJ_SIGNAL) {
lj->lioj_flags |=
LIOJ_SIGNAL_POSTED;
! timeout(process_signal, lj, 0);
}
}
}
--- 2128,2134 ----
if ((lj->lioj_flags &
(LIOJ_SIGNAL|LIOJ_SIGNAL_POSTED)) ==
LIOJ_SIGNAL) {
lj->lioj_flags |=
LIOJ_SIGNAL_POSTED;
! timeout(process_signal, aiocbe, 0);
}
}
}
*************** aio_physwakeup(bp)
*** 2004,2010 ****
--- 2146,2154 ----
ki->kaio_flags &= ~KAIO_WAKEUP;
wakeup(p);
}
+
+ }
+
+ if (aiocbe->uaiocb. aio_sigevent.sigev_notify ==
SIGEV_SIGNAL) {
+ timeout(process_signal, aiocbe, 0);
}
}
splx(s);
}
State Changed From-To: open->closed Fixed, along with kern/12053. |
The following program (~60 lines) does not get a SIGUSR1 when used with a raw device, but does get the signal with a block device. It will wait forever for a signal (pause()); doing "kill -30 <pid>" from shell prompt will cause it to execute sigusr1() and display the data it just read and the data seemed correct. BTW, how do I identify a specific AIO job with each signal? Are signals queued in FreeBSD? Thanks very much. #include <stdio.h> #include <fcntl.h> #include <sys/signal.h> #include <time.h> #include <aio.h> aiocb_t myaiocb; siginfo_t siginfo; char buf[10240]; sig_t sigusr1(int signo) { int i; printf("in sigusr1(), signo = %d\n", signo); printf("aio_error(myaiocb): %d\n", aio_error(&myaiocb)); #if 0 printf("aio buffer after read: %s\n", buf); for (i = 0; i < 500; i++) printf(" %c", buf[i]); printf("\n"); } main(argc, argv) int argc; char** argv; { int rtn; int fd; /* signal is not posted on raw partition, but okay on block device */ fd = open("/dev/rwd0s4e", O_RDONLY); /* fd = open("/dev/wd0s4e", O_RDONLY); this works. */ if (fd < 0) { perror("open failed"); exit(1); } printf("open succeeded ...\n"); signal(SIGUSR1, (sig_t) sigusr1); myaiocb.aio_fildes = fd; myaiocb.aio_buf = buf; myaiocb.aio_nbytes = 2048; myaiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL; myaiocb.aio_sigevent.sigev_signo = SIGUSR1; myaiocb.aio_sigevent.sigev_value.sival_int = 123; printf("calling aio_read ...\n"); rtn = aio_read(&myaiocb); if (rtn < 0) { perror("aio_read failed"); exit(1); } printf("aio_read succeeded\n"); /* normally get EINPROGRESS */ printf("aio_error(myaiocb): %d\n", aio_error(&myaiocb)); pause(); } How-To-Repeat: The above program will wait forever for a signal.