1
0
mirror of git://sigrok.org/libserialport synced 2023-08-10 21:13:24 +03:00

posix: Make sure blocking operations can't time out without trying.

This commit is contained in:
Martin Ling 2015-05-07 10:04:11 +01:00 committed by Uwe Hermann
parent c3cee38c3b
commit 76222ee578

View File

@ -774,6 +774,7 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
size_t bytes_written = 0; size_t bytes_written = 0;
unsigned char *ptr = (unsigned char *) buf; unsigned char *ptr = (unsigned char *) buf;
struct timeval start, delta, now, end = {0, 0}; struct timeval start, delta, now, end = {0, 0};
int started = 0;
fd_set fds; fd_set fds;
int result; int result;
@ -792,8 +793,12 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
/* Loop until we have written the requested number of bytes. */ /* Loop until we have written the requested number of bytes. */
while (bytes_written < count) { while (bytes_written < count) {
/* Wait until space is available. */ /*
if (timeout_ms) { * Check timeout only if we have run select() at least once,
* to avoid any issues if a short timeout is reached before
* select() is even run.
*/
if (timeout_ms && started) {
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (timercmp(&now, &end, >)) if (timercmp(&now, &end, >))
/* Timeout has expired. */ /* Timeout has expired. */
@ -801,6 +806,7 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
timersub(&end, &now, &delta); timersub(&end, &now, &delta);
} }
result = select(port->fd + 1, NULL, &fds, NULL, timeout_ms ? &delta : NULL); result = select(port->fd + 1, NULL, &fds, NULL, timeout_ms ? &delta : NULL);
started = 1;
if (result < 0) { if (result < 0) {
if (errno == EINTR) { if (errno == EINTR) {
DEBUG("select() call was interrupted, repeating"); DEBUG("select() call was interrupted, repeating");
@ -992,6 +998,7 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
size_t bytes_read = 0; size_t bytes_read = 0;
unsigned char *ptr = (unsigned char *) buf; unsigned char *ptr = (unsigned char *) buf;
struct timeval start, delta, now, end = {0, 0}; struct timeval start, delta, now, end = {0, 0};
int started = 0;
fd_set fds; fd_set fds;
int result; int result;
@ -1010,8 +1017,12 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
/* Loop until we have the requested number of bytes. */ /* Loop until we have the requested number of bytes. */
while (bytes_read < count) { while (bytes_read < count) {
/* Wait until data is available. */ /*
if (timeout_ms) { * Check timeout only if we have run select() at least once,
* to avoid any issues if a short timeout is reached before
* select() is even run.
*/
if (timeout_ms && started) {
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (timercmp(&now, &end, >)) if (timercmp(&now, &end, >))
/* Timeout has expired. */ /* Timeout has expired. */
@ -1019,6 +1030,7 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
timersub(&end, &now, &delta); timersub(&end, &now, &delta);
} }
result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &delta : NULL); result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &delta : NULL);
started = 1;
if (result < 0) { if (result < 0) {
if (errno == EINTR) { if (errno == EINTR) {
DEBUG("select() call was interrupted, repeating"); DEBUG("select() call was interrupted, repeating");
@ -1036,7 +1048,10 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
if (result < 0) { if (result < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
/* This shouldn't happen because we did a select() first, but handle anyway. */ /*
* This shouldn't happen because we did a
* select() first, but handle anyway.
*/
continue; continue;
else else
/* This is an actual failure. */ /* This is an actual failure. */
@ -1267,6 +1282,7 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
RETURN_OK(); RETURN_OK();
#else #else
struct timeval start, delta, now, end = {0, 0}; struct timeval start, delta, now, end = {0, 0};
int started = 0;
int result, timeout_remaining_ms; int result, timeout_remaining_ms;
struct pollfd *pollfds; struct pollfd *pollfds;
unsigned int i; unsigned int i;
@ -1298,7 +1314,12 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
/* Loop until an event occurs. */ /* Loop until an event occurs. */
while (1) { while (1) {
if (timeout_ms) { /*
* Check timeout only if we have run poll() at least once,
* to avoid any issues if a short timeout is reached before
* poll() is even run.
*/
if (timeout_ms && started) {
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (timercmp(&now, &end, >)) { if (timercmp(&now, &end, >)) {
DEBUG("Wait timed out"); DEBUG("Wait timed out");
@ -1309,6 +1330,7 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
} }
result = poll(pollfds, event_set->count, timeout_ms ? timeout_remaining_ms : -1); result = poll(pollfds, event_set->count, timeout_ms ? timeout_remaining_ms : -1);
started = 1;
if (result < 0) { if (result < 0) {
if (errno == EINTR) { if (errno == EINTR) {