From nobody@FreeBSD.ORG Wed Aug 11 06:34:22 1999
Return-Path: <nobody@FreeBSD.ORG>
Received: by hub.freebsd.org (Postfix, from userid 32767)
	id 4197A14D2E; Wed, 11 Aug 1999 06:34:22 -0700 (PDT)
Message-Id: <19990811133422.4197A14D2E@hub.freebsd.org>
Date: Wed, 11 Aug 1999 06:34:22 -0700 (PDT)
From: kwchen@lucent.com
Sender: nobody@FreeBSD.ORG
To: freebsd-gnats-submit@freebsd.org
Subject: signal is not posted for async I/O on raw devices
X-Send-Pr-Version: www-1.0

>Number:         13075
>Category:       kern
>Synopsis:       signal is not posted for async I/O on raw devices
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 11 06:40:01 PDT 1999
>Closed-Date:    Fri Jan 14 10:58:51 PST 2000
>Last-Modified:  Fri Jan 14 10:59:39 PST 2000
>Originator:     K. Herman Chen
>Release:        FreeBSD 3.2-RELEASE #6
>Organization:
Lucent Technologies
>Environment:
FreeBSD marlin 3.2-RELEASE FreeBSD 3.2-RELEASE #6: Mon Jul 19
 16:16:40 EDT 1999     lin@tampa:/usr/src/sys/compile/SMASH-CS-32  i386
>Description:
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.
>Fix:


>Release-Note:
>Audit-Trail:

From: Christopher Sedore <cmsedore@maxwell.syr.edu>
To: "'freebsd-gnats-submit@freebsd.org'" <freebsd-gnats-submit@freebsd.org>,
	"'kwchen@lucent.com'" <kwchen@lucent.com>
Cc:  
Subject: Re: kern/13075: signal is not posted for async I/O on raw devices
Date: Wed, 15 Sep 1999 13:55:09 -0400

 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 
State-Changed-By: jasone 
State-Changed-When: Fri Jan 14 10:58:51 PST 2000 
State-Changed-Why:  
Fixed, along with kern/12053. 
>Unformatted:
