Re: close on USB serial port hangs (read pending) on Snow Leopard
Re: close on USB serial port hangs (read pending) on Snow Leopard
- Subject: Re: close on USB serial port hangs (read pending) on Snow Leopard
- From: Fritz Anderson <email@hidden>
- Date: Fri, 19 Feb 2010 10:20:15 -0600
On 18 Feb 2010, at 10:30 PM, Terry Lambert wrote:
> Another non-synchronizing approach would be to use a select with a timeout, or set a vtime as well as a vmin on the descriptor. You would still be polling, but you could do it at much longer intervals, and escape the performance issues. Waking up once every 10 seconds (or whatever is a tolerable wait for a close operation) is going better than buzz-looping, no matter how you look at it.
This is just what I needed, and I thank you. I know my solution is third choice, but I'm working with a Cocoa NSThread, which denies access to pthreads.
I'd be very grateful if someone can vet my solution. I think I know enough now to proceed, but I'm away from the device till this evening. I know you all have better things to do than code review for a novice, but if I'm doing anything obviously wrong, your help could save me a lot of time.
— F
/*
In the object for which these are methods:
inputHandle: the fd for the port; -1 if no further I/O is to be attempted.
savedTTYState: the result of a tcgetattr() from initialization time.
doClose: a flag for whether polling should stop.
*/
// Called on read thread
- (int) internalClose
{
int result = tcsetattr(inputHandle, TCSANOW, &savedTTYState);
int lagHandle = inputHandle;
inputHandle = -1;
result = close(lagHandle);
return result;
}
// Called on read thread
- (ssize_t) blockingRead: (void *) buffer size: (ssize_t) bufferSize
{
ssize_t retval = 0;
fd_set permFDs;
FD_ZERO(&permFDs);
FD_SET(inputHandle, &permFDs);
while (! doClose) {
fd_set readSet;
FD_COPY(&permFDs, &readSet);
fd_set errSet;
FD_COPY(&permFDs, &errSet);
struct timeval timeout = {
0, 100000 // 100_000 microseconds = 1/10 second
};
int pending = select(inputHandle+1,
&readSet, NULL, &errSet,
&timeout);
if (pending != 0) {
if (FD_ISSET(inputHandle, &errSet)) {
// An error. Panic out.
[self internalClose];
return -1;
}
else if (FD_ISSET(inputHandle, &readSet)) {
// Data! Pull it in.
retval = read(inputHandle, buffer, bufferSize);
// 9600 baud in 0.1 seconds = ~100 bytes.
// I can afford to provide a big buffer and
// take my chances that the read won't exceed
// the buffer size.
if (retval < 0) {
[self internalClose];
}
return retval;
}
// The caller uses performSelectorOnMainThread: to
// notify a delegate of data or error.
}
}
return retval;
}
// Called on main thread
- (void) close
{
doClose = YES;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden