Skip to content

Commit 3d1dcc7

Browse files
committed
Properly handle EINTR in POSIX UDP and TCP transport profiles
Blocking I/O functions, like connect(), poll(), send() and recv(), will return -1 with errno == EINTR if the process/thread is interrupted by a signal. This is not an I/O error, but generally means the operations should be restarted. This commit implements the auto-restart behavior, which allows the transport profiles to be used in environments that generate a lot of signals, like the FreeRTOS simulator for Linux. Signed-off-by: J. S. Seldenthuis <jseldenthuis@lely.com>
1 parent 823ed61 commit 3d1dcc7

File tree

4 files changed

+100
-14
lines changed

4 files changed

+100
-14
lines changed

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ bool uxr_init_tcp_platform(
2424
const char* port)
2525
{
2626
bool rv = false;
27+
int errsv = errno;
2728

2829
switch (ip_protocol)
2930
{
@@ -60,7 +61,13 @@ bool uxr_init_tcp_platform(
6061
{
6162
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
6263
{
63-
if (0 == connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen))
64+
int connect_rv;
65+
do
66+
{
67+
errno = errsv;
68+
connect_rv = connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen);
69+
} while (-1 == connect_rv && EINTR == errno);
70+
if (0 == connect_rv)
6471
{
6572
platform->poll_fd.events = POLLIN;
6673
rv = true;
@@ -86,7 +93,13 @@ size_t uxr_write_tcp_data_platform(
8693
uint8_t* errcode)
8794
{
8895
size_t rv = 0;
89-
ssize_t bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0);
96+
int errsv = errno;
97+
ssize_t bytes_sent;
98+
do
99+
{
100+
errno = errsv;
101+
bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0);
102+
} while (-1 == bytes_sent && EINTR == errno);
90103
if (-1 != bytes_sent)
91104
{
92105
rv = (size_t)bytes_sent;
@@ -107,10 +120,21 @@ size_t uxr_read_tcp_data_platform(
107120
uint8_t* errcode)
108121
{
109122
size_t rv = 0;
110-
int poll_rv = poll(&platform->poll_fd, 1, timeout);
123+
int errsv = errno;
124+
int poll_rv;
125+
do
126+
{
127+
errno = errsv;
128+
poll_rv = poll(&platform->poll_fd, 1, timeout);
129+
} while (-1 == poll_rv && EINTR == errno);
111130
if (0 < poll_rv)
112131
{
113-
ssize_t bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0);
132+
ssize_t bytes_received;
133+
do
134+
{
135+
errno = errsv;
136+
bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0);
137+
} while (-1 == bytes_received && EINTR == errno);
114138
if (-1 != bytes_received)
115139
{
116140
rv = (size_t)bytes_received;

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ bool uxr_init_tcp_platform(
2626
const char* port)
2727
{
2828
bool rv = false;
29+
int errsv = errno;
2930

3031
switch (ip_protocol)
3132
{
@@ -62,7 +63,13 @@ bool uxr_init_tcp_platform(
6263
{
6364
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
6465
{
65-
if (0 == connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen))
66+
int connect_rv;
67+
do
68+
{
69+
errno = errsv;
70+
connect_rv = connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen);
71+
} while (-1 == connect_rv && EINTR == errno);
72+
if (0 == connect_rv)
6673
{
6774
rv = true;
6875
break;
@@ -87,7 +94,13 @@ size_t uxr_write_tcp_data_platform(
8794
uint8_t* errcode)
8895
{
8996
size_t rv = 0;
90-
ssize_t bytes_sent = send(platform->fd, (void*)buf, len, 0);
97+
int errsv = errno;
98+
ssize_t bytes_sent;
99+
do
100+
{
101+
errno = errsv;
102+
bytes_sent = send(platform->fd, (void*)buf, len, 0);
103+
} while (-1 == bytes_sent && EINTR == errno);
91104
if (-1 != bytes_sent)
92105
{
93106
rv = (size_t)bytes_sent;
@@ -108,6 +121,7 @@ size_t uxr_read_tcp_data_platform(
108121
uint8_t* errcode)
109122
{
110123
size_t rv = 0;
124+
int errsv = errno;
111125

112126
timeout = (timeout <= 0) ? 1 : timeout;
113127

@@ -117,7 +131,12 @@ size_t uxr_read_tcp_data_platform(
117131

118132
setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
119133

120-
ssize_t bytes_received = recv(platform->fd, (void*)buf, len, 0);
134+
ssize_t bytes_received;
135+
do
136+
{
137+
errno = errsv;
138+
bytes_received = recv(platform->fd, (void*)buf, len, 0);
139+
} while (-1 == bytes_received && EINTR == errno);
121140
if (-1 != bytes_received)
122141
{
123142
rv = (size_t)bytes_received;

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ bool uxr_init_udp_platform(
1414
const char* port)
1515
{
1616
bool rv = false;
17+
int errsv = errno;
1718

1819
switch (ip_protocol)
1920
{
@@ -47,7 +48,13 @@ bool uxr_init_udp_platform(
4748
{
4849
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
4950
{
50-
if (0 == connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen))
51+
int connect_rv;
52+
do
53+
{
54+
errno = errsv;
55+
connect_rv = connect(platform->poll_fd.fd, ptr->ai_addr, ptr->ai_addrlen);
56+
} while (-1 == connect_rv && EINTR == errno);
57+
if (0 == connect_rv)
5158
{
5259
platform->poll_fd.events = POLLIN;
5360
rv = true;
@@ -73,7 +80,13 @@ size_t uxr_write_udp_data_platform(
7380
uint8_t* errcode)
7481
{
7582
size_t rv = 0;
76-
ssize_t bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0);
83+
int errsv = errno;
84+
ssize_t bytes_sent;
85+
do
86+
{
87+
errno = errsv;
88+
bytes_sent = send(platform->poll_fd.fd, (void*)buf, len, 0);
89+
} while (-1 == bytes_sent && EINTR == errno);
7790
if (-1 != bytes_sent)
7891
{
7992
rv = (size_t)bytes_sent;
@@ -94,10 +107,21 @@ size_t uxr_read_udp_data_platform(
94107
uint8_t* errcode)
95108
{
96109
size_t rv = 0;
97-
int poll_rv = poll(&platform->poll_fd, 1, timeout);
110+
int errsv = errno;
111+
int poll_rv;
112+
do
113+
{
114+
errno = errsv;
115+
poll_rv = poll(&platform->poll_fd, 1, timeout);
116+
} while (-1 == poll_rv && EINTR == errno);
98117
if (0 < poll_rv)
99118
{
100-
ssize_t bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0);
119+
ssize_t bytes_received;
120+
do
121+
{
122+
errno = errsv;
123+
bytes_received = recv(platform->poll_fd.fd, (void*)buf, len, 0);
124+
} while (-1 == bytes_received && EINTR == errno);
101125
if (-1 != bytes_received)
102126
{
103127
rv = (size_t)bytes_received;

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ bool uxr_init_udp_platform(
1616
const char* port)
1717
{
1818
bool rv = false;
19+
int errsv = errno;
1920

2021
switch (ip_protocol)
2122
{
@@ -49,7 +50,13 @@ bool uxr_init_udp_platform(
4950
{
5051
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
5152
{
52-
if (0 == connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen))
53+
int connect_rv;
54+
do
55+
{
56+
errno = errsv;
57+
connect_rv = connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen);
58+
} while (-1 == connect_rv && EINTR == errno);
59+
if (0 == connect_rv)
5360
{
5461
rv = true;
5562
break;
@@ -74,7 +81,13 @@ size_t uxr_write_udp_data_platform(
7481
uint8_t* errcode)
7582
{
7683
size_t rv = 0;
77-
ssize_t bytes_sent = send(platform->fd, (void*)buf, len, 0);
84+
int errsv = errno;
85+
ssize_t bytes_sent;
86+
do
87+
{
88+
errno = errsv;
89+
bytes_sent = send(platform->fd, (void*)buf, len, 0);
90+
} while (-1 == bytes_sent && EINTR == errno);
7891
if (-1 != bytes_sent)
7992
{
8093
rv = (size_t)bytes_sent;
@@ -95,6 +108,7 @@ size_t uxr_read_udp_data_platform(
95108
uint8_t* errcode)
96109
{
97110
size_t rv = 0;
111+
int errsv = errno;
98112

99113
timeout = (timeout <= 0) ? 1 : timeout;
100114

@@ -104,7 +118,12 @@ size_t uxr_read_udp_data_platform(
104118

105119
setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
106120

107-
ssize_t bytes_received = recv(platform->fd, (void*)buf, len, 0);
121+
ssize_t bytes_received;
122+
do
123+
{
124+
errno = errsv;
125+
bytes_received = recv(platform->fd, (void*)buf, len, 0);
126+
} while (-1 == bytes_received && EINTR == errno);
108127
if (-1 != bytes_received)
109128
{
110129
rv = (size_t)bytes_received;

0 commit comments

Comments
 (0)