Dale Wolfe(deleted)
|
SIGSEGV issues with aio functions
|
Dale Wolfe(deleted)
10/30/2013 11:03 AM
post106404
|
SIGSEGV issues with aio functions
The overly simplistic description of what I am experiencing is a SIGSEGV error within an aio thread. See the attachment
.
This is what we know:
1) It only happens after executing aio_read. Occasionally we also get this error within a devctrl thread.
2) I have never observed this after executing an aio_write.
3) We experience this issue when using a callback method with the aio_sigevent
Here’s the cleaned version of this code: Note that this code is called simultaneously from 3 threads within our
application for 3 different UARTS.
static void _Hal_DataRxd (union sigval val);
static void _Hal_DataRxd (union sigval val)
{
OS_SemPost((tOS_SEMAPHORE)val.sival_int);
}
tINT16 Hal_UartGetBlock(tHAL_UART_PORT Port, tUINT8* pData, tINT16 SizeOfRequest)
{
tUart *pUart; // Pointer to our UART control structure.
struct aiocb Async; // Asynchronous control block for the UART.
const struct aiocb *pList[1] = { &(Async) }; // List of our asynchronous control blocks.
struct timespec Timeout; // Interval timeout to wait for asynchronous transfer.
int Retry; // TODO: comment
int Result; // The resulting exit code of system calls.
ssize_t Count; // The number of bytes read from the driver.
tERROR Error;
// Validate our arguments.
if (Port >= dHAL_INFO_UART_TOTAL)
{ return (dEOF); }
if (pData == dNULL)
{ return (dEOF); }
if (MaxSize <= 0)
{ return (dEOF); }
pUart = &(Uarts[Port]); // Grab the requested UART.
// Check that the port is not already opened.
if (pUart->Fd == -1)
{ return (dEOF); }
// Setup our asynchronous control block for the UART.
Async.aio_fildes = pUart->Fd;
Async.aio_buf = (volatile void *)pData;
Async.aio_nbytes = SizeOfRequest;
Async.aio_offset = 0;
Async.aio_reqprio = 0;
Async.aio_lio_opcode = LIO_NOP;
SIGEV_THREAD_INIT(&(Async.aio_sigevent), &_Hal_DataRxd, pUart->pSem, NULL );
// Queue the asynchronous read.
Result = aio_read((void*)&(Async));
if (Result < 0)
{
aio_error(&(Async));
return (dEOF);
}
Error = OS_SemPend(pUart->pSem, 30);
if(Error != dOS_ERROR_NONE)
return(0);
// Get the asynchronous transfer byte count.
Count = aio_return((void*)&(Async));
if (Count < 0)
{ Count = 0; }
return (Count);
}
}
We also see another issue when NOT using the callback method.
Here we use the aio_suspend. We implemented a do-while loop because we get an error code of 236 returned from the
aio_suspend function (system resource busy). It usually takes multiple retries before the system resource is no longer
busy.
Occasionally, it is busy indefinitely (loop increased to 1 billion). We’ve added usleeps of ~2ms before the
aio_suspend in this code and it tends to relieve some of the retries but not all.
Besides and error 236 from aio_suspend we occasionally get a SIGSEGV type errors here too like the above callback method
.
// Setup our asynchronous control block for the UART.
Async.aio_fildes = pUart->Fd;
Async.aio_buf = (volatile void *)pData;
Async.aio_nbytes = SizeOfRequest;
Async.aio_offset = 0;
Async.aio_reqprio = 0;
Async.aio_lio_opcode = LIO_NOP;
SIGEV_NONE_INIT(&(Async.aio_sigevent));
Result = aio_read((void*)&(Async));
if (Result < 0)
{
aio_error(&(Async));
return (dEOF);
}
// Determine the relative timeout delay to wait.
Timeout.tv_sec = 0;
Timeout.tv_nsec = (30 * 1000000);
Retry = 0;
do
{
Retry++;
Result = aio_suspend(pList, 1, &Timeout);
if (Result < 0)
{
Result = aio_error(&(Async));
if (Result == dOS_EAGAIN)
break;
}
} while ((Result != dOS_EOK) && (Retry < 10));
// Get the asynchronous transfer byte count.
...
View Full Message
|
|
|