Abort a blocking read()

Discussion to talk about software related topics only.
Post Reply
DBrunermer
Posts: 67
Joined: Thu Apr 21, 2011 7:06 am
Location: Pittsburgh, PA

Abort a blocking read()

Post by DBrunermer »

MOD 54415 ; NNDK 4.7.7

In one task, I have a blocking read(...) function. Occasionally, I need to abort this operation from a different thread. Is this possible?

I tried calling close() on the file id from the other task, but that doesn't seem to do it.
Thanks, Dan
sulliwk06
Posts: 118
Joined: Tue Sep 17, 2013 7:14 am

Re: Abort a blocking read()

Post by sulliwk06 »

Switching to a select(...) call instead of a read would give you some options. You could select in a loop with a short timeout and check a global flag to see if you need to bail out. You could look for an error on the file descriptor when you close it, or if you want you could have the select check 2 different file descriptors and use one to send a message to bail out.
DBrunermer
Posts: 67
Joined: Thu Apr 21, 2011 7:06 am
Location: Pittsburgh, PA

Re: Abort a blocking read()

Post by DBrunermer »

Thanks for the response, sulliwk06. For now I'm trying a ReadWithTimeout() with 2 as the TO value. In the routine where I need to change the file's read location, if I sense the port is open, instead of closing it, I change the variable I need to change and do a OSTimeDly(4) and just sort of hope that fixes it all up.
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Abort a blocking read()

Post by pbreed »

Here is a nasty hack.....
VERY IMPORTANT THAT YOU READ THE NOTE AT THE END....
This code should work, it has not been tested at all.
I just typed it here, I did not even check to see if it compiles....

#include <iointernal.h>

void AbortAbleRead(int fd, char * buffer, int count)
{
fd_set read_fds;
fd_set error_fds;
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );
FD_SET( fd, &error_fds );
select( FD_SETSIZE, &read_fds, (fd_set *) 0, &error_fds,0);
if ( FD_ISSET( fd, &read_fds ) )
{
return read(fd,buffer,count);
}
//No data to read so we must have errored out of the select.
return -1;
}


void ForceReadAbort(int fd)
[
SetHaveError(fd );
}

void ClearReadAbort(int fd)
{
int read_error= getsocketerror( fd );
if((read_error) && (read_error!= TCP_ERR_NOSUCH_SOCKET)) return;
ClrHaveError(fd );
}

Important note...
Your messing with the internals of the world...
If this is an SSL or TLS or ssh fd, then I would not do this.
If you want an abort on absolutely any type of read I'd create a 2nd fd and use that in the select to abort.
If you need help with that code, please ask.

If this is a fd for a serial port then you will be fine.
If this is a TCP fd then the clear read abort will restore the error rather than clear if tcp really had an error.

If you ever call ForceReadAbort you must call ClearReadAbort...
There is a race condition here, if you call ForceRead abort and the fd gets data at the same time...
Then it will return the read data, not a -1.
So make sure your logic calls ClearReadAbort whenever ForceReadAbort is called.... even if your read returns data.
Its probably ok to call ClearReadAbort every time... (you could even put it in the Read call.
Hope this helps
Post Reply