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:
parent
c3cee38c3b
commit
76222ee578
34
serialport.c
34
serialport.c
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user