简体   繁体   中英

How to get user data for aio signal handler in Mac OS X

I am attempting to use the aio_* functions for asynchronous file IO under Mac OS X, but I am having problems with getting some form of user data into the signal handler.

This is the code that sets up an operation:

class aio_context {
public:
    aio_context(int fildes, boost::uint64_t offset,
        const MyBufferClassPtr &buffer)
    {
        // The aiocb struct must be zeroed
        memset(&m_aiocb, 0, sizeof(struct aiocb));

        // Set what to do
        m_aiocb.aio_fildes = fildes;
        m_aiocb.aio_buf = buffer->data();
        m_aiocb.aio_nbytes = buffer->size();
        m_aiocb.aio_offset = offset;

        // Set notification
        m_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
        m_aiocb.aio_sigevent.sigev_signo = SIGUSR1;

        // ATTEMPT TO SET A VALUE THAT CAN BE READ IN THE HANDLER
        m_aiocb.aio_sigevent.sigev_value.sival_ptr = this;
    }

    struct aiocb* GetAiocbp()
    {
        return &m_aiocb;
    }

private:
    struct aiocb m_aiocb;
    // Some more context here
};

This is then called from somewhere else like this:

aio_context *ctx = new aio_context(file_descriptor, offset, data);
// set some more context here
int ret = aio_write(ctx->GetAiocbp());
if (0 != ret) {
    // throw something
}

My signal handling setup looks like this:

sigemptyset(&m_CurrentSIGHandler.sa_mask);
m_CurrentSIGHandler.sa_sigaction = aio_completion_handler;
m_CurrentSIGHandler.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &m_CurrentSIGHandler, &m_PreviousSIGHandler);

and the actual handler like this:

void aio_completion_handler(int signo, siginfo_t *info, void *context)
{
    if (info->si_signo == SIGUSR1) {
        // Get the aio operation
        aio_context *ctx = static_cast<aio_context *>(info->si_value.sival_ptr);

        // THIS ASSERT ALWAYS FAILS - ctx IS NULL
        assert(ctx);

        // next check aio_error and aio_return using the aicb member of the ctx
        // ...
    }
}

So the problem is that the si_value.sival_ptr is always NULL in the signal handler, instead of being the aio_context pointer that I set in the aiocb struct. I must have misunderstood something on how to do this, so can anyone tell me what I am doing wrong?

I am running on MacOSX 10.6, but I am (at least attempting to) compiling for 10.5 if that matters.

Also, the answer to this question seems to indicate that AIO should be disregarded entirely - is this really the case?

Update:

I found someone else having the same problem at http://lists.apple.com/archives/darwin-dev/2008/Oct/msg00054.html .

I also reviewed the kernel code at http://www.opensource.apple.com/source/xnu/xnu-1504.9.26/bsd/kern/kern_aio.c and if I understand it correctly, sigev_value is indeed completely ignored. I'm really at a loss here on what the expected usage of the aio_* functions is on Mac OS X. It does not appear to be the case that they can be used in the manner above anyway. Have I misunderstood something or are the aio_* functions a dead end for my use case?

Mac OS X does not support real time signals ([RTS] in the posix specification ), which is the section of POSIX which adds userdata pointers to signals. This makes Mac OS X very hard to use efficiently with AIO. Your only option is to loop through all your outstanding jobs and handle the ones that are complete.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM