Ich versuche auf ein serielles Device über einen BSD-Pfad zuzugreifen. Das klappt soweit auch.
Allerdings bekomme ich es nicht hin, den "read" mit einem Timeout zu versehen.
Eigentlich dachte ich, das würde über die "options.c_cc[VMIN] /options.c_cc[VTIME] " Parameter gesteuert. Funktioniert aber nicht.
Dadurch bleibt mir die ganze Geschichte "hängen", wenn ich auf ein Device zugreife, das nicht antwortet.
Wenn ich den File-Descriptor auf "non-blocking" setze und beim Read einen eigenen (manuellen) Timeout einbaue klappt's zwar wie gewünscht, aber das kanns ja eigentlich nicht sein.
Hier der beteiligte Code:
Alles anzeigen
Sobald ich die Zeilen 17+18 nicht auskommentiere, müsste doch eigentlich der in den Zeilen 25+26 definierte Timeout gelten, oder nicht?
Bei mir tut er's nicht, die nachfolgende Funktion hängt dann (beim Versuch auf ein nicht reagierendes Device zuzugreifen) auf unbestimmte Zeit in Zeile 23 fest.
Zum Testen habe ich (wenn ich oben die Zeilen 17+18 auskommentiere, der File-Descriptor also auf NONBLOCKING bleibt) einen "manuellen" Timeout eingebaut (Zeilen 14+15 bzw. 37-41). Dann funktioniert auch alles wunderbar, aber ich dachte eigentlich, dass sich da der Kernel drum kümmern würde...
Alles anzeigen
Weiß jemand was ich falsch mache?
Allerdings bekomme ich es nicht hin, den "read" mit einem Timeout zu versehen.
Eigentlich dachte ich, das würde über die "options.c_cc[VMIN] /options.c_cc[VTIME] " Parameter gesteuert. Funktioniert aber nicht.
Dadurch bleibt mir die ganze Geschichte "hängen", wenn ich auf ein Device zugreife, das nicht antwortet.
Wenn ich den File-Descriptor auf "non-blocking" setze und beim Read einen eigenen (manuellen) Timeout einbaue klappt's zwar wie gewünscht, aber das kanns ja eigentlich nicht sein.
Hier der beteiligte Code:
Quellcode
- - (BOOL)openSerialPort
- {
- BOOL success = YES;
- if(fileDescriptor == -1)
- {
- @try
- {
- struct termios options;
- fileDescriptor = open([bsdPath UTF8String], O_RDWR | O_NOCTTY | O_NONBLOCK);
- if (fileDescriptor == -1)
- [NSException raise:@"openSerialPort" format:@"Error opening serial port %@ - %s (%d).", bsdPath, strerror(errno), errno];
- if (ioctl(fileDescriptor, TIOCEXCL) == -1)
- [NSException raise:@"openSerialPort" format:@"Error setting TIOCEXCL on %@ - %s (%d).", bsdPath, strerror(errno), errno];
- // fileDescriptor auf "blocking setzen"
- // if (fcntl(fileDescriptor, F_SETFL, 0) == -1)
- // [NSException raise:@"openSerialPort" format:@"Error clearing O_NONBLOCK %@ - %s (%d).", bsdPath, strerror(errno), errno];
- if (tcgetattr(fileDescriptor, &originalTTYAttrs) == -1)
- [NSException raise:@"openSerialPort" format:@"Error getting tty attributes %@ - %s (%d).", bsdPath, strerror(errno), errno];
- options = originalTTYAttrs;
- cfmakeraw(&options);
- options.c_cc[VMIN] = 1;
- options.c_cc[VTIME] = 5;
- cfsetspeed(&options, B38400);
- options.c_cflag &= ~PARENB;
- options.c_cflag &= ~CSTOPB;
- options.c_cflag &= ~CSIZE;
- options.c_cflag |= CS8;
- options.c_cflag |= CCTS_OFLOW;
- options.c_cflag |= CRTS_IFLOW;
- if (tcsetattr(fileDescriptor, TCSANOW, &options) == -1)
- [NSException raise:@"openSerialPort" format:@"Error setting tty attributes %@ - %s (%d).", bsdPath, strerror(errno), errno];
- }
- @catch(NSException* exception)
- {
- PSErrorLog([exception reason],nil);
- [self closeSerialPort];
- success = NO;
- }
- }
- return success;
- }
Sobald ich die Zeilen 17+18 nicht auskommentiere, müsste doch eigentlich der in den Zeilen 25+26 definierte Timeout gelten, oder nicht?
Bei mir tut er's nicht, die nachfolgende Funktion hängt dann (beim Versuch auf ein nicht reagierendes Device zuzugreifen) auf unbestimmte Zeit in Zeile 23 fest.
Zum Testen habe ich (wenn ich oben die Zeilen 17+18 auskommentiere, der File-Descriptor also auf NONBLOCKING bleibt) einen "manuellen" Timeout eingebaut (Zeilen 14+15 bzw. 37-41). Dann funktioniert auch alles wunderbar, aber ich dachte eigentlich, dass sich da der Kernel drum kümmern würde...
Quellcode
- - (PacketResponse*)runCommand:(NSData*)packet
- {
- PacketResponse* response = nil;
- if (packet && packet.length >= 4)
- {
- NSLog(@"Sending %@", [packet description]);
- ssize_t numBytesSent = write(fileDescriptor, [packet bytes], [packet length]);
- if (numBytesSent == -1)
- {
- PSErrorLog(@"Error writing to device - %s (%d).", strerror(errno), errno);
- }
- // Manuelles Timeout
- BOOL timeout = NO;
- NSDate* startTime = [NSDate date];
- NSLog(@"Waiting for response");
- response = [[PacketResponse alloc] init];
- uint8_t buffer[256];
- ssize_t numBytesRead=0;
- do
- {
- numBytesRead = read(fileDescriptor, buffer, 255);
- if (numBytesRead == -1)
- {
- usleep(100);
- }
- else if (numBytesRead > 0)
- {
- if([response processBytes:buffer length:numBytesRead])
- break; // PacketResponse complete...
- }
- else
- NSLog(@"Nothing read.");
- // Manuelles Timeout
- timeout = (-[startTime timeIntervalSinceNow]>1.);
- if(timeout)
- PSErrorLog(@"*** Timeout");
- } while (numBytesRead > 0 && !timeout);
- if(numBytesRead == -1)
- PSErrorLog(@"Error reading from printer - %s (%d).", strerror(errno), errno);
- }
- return response;
- }
Weiß jemand was ich falsch mache?
Bevor man jemanden kritisiert, sollte man zuerst ein paar Meilen in dessen Schuhen gehen!
Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...
Erstens ist man dann in sicherem Abstand und zweitens hat man die Schuhe...