Skip to content

Commit d07b5e3

Browse files
client: check wait return code in waitAny
Currently, we do not check the return code of `wait` in `waitAny`. If there is an error, we must log it and return a `nullopt`. Closes #121
1 parent 89311fd commit d07b5e3

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/Client/Connector.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,10 @@ Connector<BUFFER, NetProvider>::waitAny(int timeout)
300300
Timer timer{timeout};
301301
timer.start();
302302
while (m_ReadyToDecode.empty()) {
303-
m_NetProvider.wait(timer.timeLeft());
303+
if (m_NetProvider.wait(timer.timeLeft()) != 0) {
304+
LOG_ERROR("Failed to poll connections: ", strerror(errno));
305+
return std::nullopt;
306+
}
304307
if (timer.isExpired())
305308
break;
306309
}

test/ClientTest.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include "../src/Client/LibevNetProvider.hpp"
3636
#include "../src/Client/Connector.hpp"
3737

38+
#include <thread>
39+
3840
const char *localhost = "127.0.0.1";
3941
int port = 3301;
4042
int dummy_server_port = 3302;
@@ -1144,6 +1146,12 @@ response_decoding(Connector<BUFFER, NetProvider> &client)
11441146
client.close(conn);
11451147
}
11461148

1149+
void
1150+
sigusr_handler(int signo)
1151+
{
1152+
fail_unless(signo != SIGINT);
1153+
}
1154+
11471155
/** Checks all available `wait` methods of connector. */
11481156
template <class BUFFER, class NetProvider>
11491157
void
@@ -1324,6 +1332,30 @@ test_wait(Connector<BUFFER, NetProvider> &client)
13241332
fail_unless(result.header.sync == static_cast<int>(f1));
13251333
fail_unless(result.header.code == 0);
13261334

1335+
#ifdef __linux__
1336+
TEST_CASE("waitAny internal wait failure (gh-121)");
1337+
static constexpr double LONG_SLEEP_TIME = 2;
1338+
f = conn.call("remote_sleep", std::forward_as_tuple(LONG_SLEEP_TIME));
1339+
fail_unless(!conn.futureIsReady(f));
1340+
pthread_t tid = pthread_self();
1341+
struct sigaction act;
1342+
act.sa_handler = sigusr_handler;
1343+
act.sa_flags = 0;
1344+
sigemptyset(&act.sa_mask);
1345+
sigaction(SIGUSR1, &act, nullptr);
1346+
auto &&signal_thread = std::thread([tid] {
1347+
sleep(LONG_SLEEP_TIME / 2);
1348+
pthread_kill(tid, SIGUSR1);
1349+
});
1350+
fail_unless(!client.waitAny().has_value());
1351+
fail_unless(client.waitAny().has_value());
1352+
fail_unless(conn.futureIsReady(f));
1353+
response = conn.getResponse(f);
1354+
fail_unless(response.has_value());
1355+
signal_thread.join();
1356+
sigaction(SIGUSR1, nullptr, nullptr);
1357+
#endif /* __linux__ */
1358+
13271359
client.close(conn);
13281360
}
13291361

0 commit comments

Comments
 (0)