Search code examples
aio

aio_write failing on release builds


I'm using aio_write it is working in a debug build but not in release. I've checked the constructor that everything is initialized and I'm not getting any warnings about uninitialized variables. The class collects data that is to be written to disc in 16K chunks. If the data is less than 16K, it works, even in release builds. If the data is larger than 16K, only the first chunk is written. WriteBuffer::ContinueWriteToFile returns WriteFileState_Active indefinitely.

WriteBuffer_posix.h:

class WriteBufferPlatformData
{
public:
    WriteBufferPlatformData();
    ~WriteBufferPlatformData();

    aiocb aioData;
    WriteBuffer::BufferVector::iterator currentBuffer;
};

WriteBuffer_posix.cpp:

WriteBufferPlatformData::WriteBufferPlatformData() :
    aioData(),
    currentBuffer()
{
    memset(&aioData,0,sizeof(aioData));
    aioData.aio_fildes=-1;
}

WriteBufferPlatformData::~WriteBufferPlatformData()
{
    if (0<=aioData.aio_fildes) {
        close(aioData.aio_fildes);
    }
}

WriteBuffer::WriteFileState WriteBuffer::StartWriteToFile(const char * filename)
{
    NYMPH_ASSERT(0>m_platformData->aioData.aio_fildes);

    m_platformData->aioData.aio_fildes=open(filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

    NYMPH_ASSERT2(0<=m_platformData->aioData.aio_fildes,"Could not open file for writing: %s (%d)",filename,errno);
    if (0>m_platformData->aioData.aio_fildes) {
        return WriteFileState_Failed;
    }

    if (m_buffers.empty()) {
        close(m_platformData->aioData.aio_fildes);
        m_platformData->aioData.aio_fildes=-1;
        return WriteFileState_Complete;
    }

    m_isWriting=true;
    m_platformData->currentBuffer=m_buffers.begin();
    return ContinueWriteToFile();
}

WriteBuffer::WriteFileState WriteBuffer::ContinueWriteToFile()
{
    NYMPH_ASSERT(0<=m_platformData->aioData.aio_fildes);

    if (0!=m_platformData->aioData.aio_nbytes) {
        int writeErrno=aio_error(&(m_platformData->aioData));
        if (EINPROGRESS==writeErrno) {
            return WriteFileState_Active;
        }

        NYMPH_ASSERT(aio_return(&(m_platformData->aioData))==m_platformData->aioData.aio_nbytes);
        m_platformData->aioData.aio_nbytes=0;
        ++(m_platformData->currentBuffer);

        if (m_buffers.end()==m_platformData->currentBuffer) {
            close(m_platformData->aioData.aio_fildes);
            m_platformData->aioData.aio_fildes=-1;
            return WriteFileState_Complete;
        }
    }

    if (0==m_platformData->aioData.aio_nbytes) {
        m_platformData->aioData.aio_buf=*(m_platformData->currentBuffer);
        if (m_buffers.back()==m_platformData->aioData.aio_buf) {
            m_platformData->aioData.aio_nbytes=m_offset;
        } else {
            m_platformData->aioData.aio_nbytes=kBufferSize;
        }
        m_platformData->aioData.aio_offset=lseek(m_platformData->aioData.aio_fildes,0,SEEK_END);

        if (0!=aio_write(&(m_platformData->aioData))) {
            m_platformData->aioData.aio_nbytes=0;
            NYMPH_ASSERT(EAGAIN==errno);
            if (EAGAIN!=errno) {
                close(m_platformData->aioData.aio_fildes);
                m_platformData->aioData.aio_fildes=-1;
                return WriteFileState_Failed;
            }
        }
    }

    return WriteFileState_Active;
}

Solution

  • Despite what I have read in the man page, it seems that calling aio_return is required and changing the NYMPH_ASSERT(aio_return... to NYMPH_VERIFY(aio_return... corrected the problem.