Skip to content

Commit 2bfdfd5

Browse files
committed
Prevent uxr_read_*_data_platform() from blocking too long
This commit recomputes the timeout in uxr_read_*_data_platform() after each occurrence of an EINTR interrupt. This ensures that the function will never block longer than the specified timeout. Signed-off-by: J. S. Seldenthuis <jseldenthuis@lely.com>
1 parent aa4e929 commit 2bfdfd5

File tree

4 files changed

+48
-24
lines changed

4 files changed

+48
-24
lines changed

src/c/profile/transport/ip/tcp/tcp_transport_posix.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <uxr/client/profile/transport/ip/tcp/tcp_transport_posix.h>
2+
#include <uxr/client/util/time.h>
23
#include "tcp_transport_internal.h"
34

45
#include <arpa/inet.h>
@@ -121,11 +122,15 @@ size_t uxr_read_tcp_data_platform(
121122
{
122123
size_t rv = 0;
123124
int errsv = errno;
125+
int64_t start_timestamp = uxr_millis();
126+
int remaining_time = timeout;
124127
int poll_rv;
125128
do
126129
{
127130
errno = errsv;
128-
poll_rv = poll(&platform->poll_fd, 1, timeout);
131+
remaining_time = (remaining_time <= 0) ? 0 : remaining_time;
132+
poll_rv = poll(&platform->poll_fd, 1, remaining_time);
133+
remaining_time = timeout - (int)(uxr_millis() - start_timestamp);
129134
} while (-1 == poll_rv && EINTR == errno);
130135
if (0 < poll_rv)
131136
{

src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <uxr/client/profile/transport/ip/tcp/tcp_transport_posix_nopoll.h>
2+
#include <uxr/client/util/time.h>
23
#include "tcp_transport_internal.h"
34

45
#include <sys/types.h>
@@ -123,23 +124,29 @@ size_t uxr_read_tcp_data_platform(
123124
size_t rv = 0;
124125
int errsv = errno;
125126

126-
timeout = (timeout <= 0) ? 1 : timeout;
127-
128-
struct timeval tv;
129-
tv.tv_sec = timeout / 1000;
130-
tv.tv_usec = (timeout % 1000) * 1000;
131-
132-
if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
133-
{
134-
*errcode = 1;
135-
return 0;
136-
}
127+
int64_t start_timestamp = uxr_millis();
128+
int remaining_time = timeout;
137129

138130
ssize_t bytes_received;
139131
do
140132
{
141133
errno = errsv;
134+
135+
remaining_time = (remaining_time <= 0) ? 1 : remaining_time;
136+
137+
struct timeval tv;
138+
tv.tv_sec = remaining_time / 1000;
139+
tv.tv_usec = (remaining_time % 1000) * 1000;
140+
141+
if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
142+
{
143+
*errcode = 1;
144+
return 0;
145+
}
146+
142147
bytes_received = recv(platform->fd, (void*)buf, len, 0);
148+
149+
remaining_time = timeout - (int)(uxr_millis() - start_timestamp);
143150
} while (-1 == bytes_received && EINTR == errno);
144151
if (-1 != bytes_received)
145152
{

src/c/profile/transport/ip/udp/udp_transport_posix.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <uxr/client/profile/transport/ip/udp/udp_transport_posix.h>
2+
#include <uxr/client/util/time.h>
23
#include "udp_transport_internal.h"
34

45
#include <arpa/inet.h>
@@ -108,11 +109,15 @@ size_t uxr_read_udp_data_platform(
108109
{
109110
size_t rv = 0;
110111
int errsv = errno;
112+
int64_t start_timestamp = uxr_millis();
113+
int remaining_time = timeout;
111114
int poll_rv;
112115
do
113116
{
114117
errno = errsv;
115-
poll_rv = poll(&platform->poll_fd, 1, timeout);
118+
remaining_time = (remaining_time <= 0) ? 0 : remaining_time;
119+
poll_rv = poll(&platform->poll_fd, 1, remaining_time);
120+
remaining_time = timeout - (int)(uxr_millis() - start_timestamp);
116121
} while (-1 == poll_rv && EINTR == errno);
117122
if (0 < poll_rv)
118123
{

src/c/profile/transport/ip/udp/udp_transport_posix_nopoll.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <uxr/client/profile/transport/ip/udp/udp_transport_posix_nopoll.h>
2+
#include <uxr/client/util/time.h>
23
#include "udp_transport_internal.h"
34

45
#include <sys/types.h>
@@ -110,23 +111,29 @@ size_t uxr_read_udp_data_platform(
110111
size_t rv = 0;
111112
int errsv = errno;
112113

113-
timeout = (timeout <= 0) ? 1 : timeout;
114-
115-
struct timeval tv;
116-
tv.tv_sec = timeout / 1000;
117-
tv.tv_usec = (timeout % 1000) * 1000;
118-
119-
if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
120-
{
121-
*errcode = 1;
122-
return 0;
123-
}
114+
int64_t start_timestamp = uxr_millis();
115+
int remaining_time = timeout;
124116

125117
ssize_t bytes_received;
126118
do
127119
{
128120
errno = errsv;
121+
122+
remaining_time = (remaining_time <= 0) ? 1 : remaining_time;
123+
124+
struct timeval tv;
125+
tv.tv_sec = remaining_time / 1000;
126+
tv.tv_usec = (remaining_time % 1000) * 1000;
127+
128+
if (0 != setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
129+
{
130+
*errcode = 1;
131+
return 0;
132+
}
133+
129134
bytes_received = recv(platform->fd, (void*)buf, len, 0);
135+
136+
remaining_time = timeout - (int)(uxr_millis() - start_timestamp);
130137
} while (-1 == bytes_received && EINTR == errno);
131138
if (-1 != bytes_received)
132139
{

0 commit comments

Comments
 (0)