Skip to content

Fix libmodbus build for mingw #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: rtu_usb
Choose a base branch
from
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ AC_CHECK_DECLS([__CYGWIN__])
AC_SEARCH_LIBS(accept, network socket)

# Checks for library functions.
AC_CHECK_FUNCS([accept4 gai_strerror getaddrinfo gettimeofday select socket strerror strlcpy])
AC_CHECK_FUNCS([accept4 gai_strerror getaddrinfo gettimeofday select socket strerror strlcpy setvbuf])

# Required for MinGW with GCC v4.8.1 on Win7
AC_DEFINE(WINVER, 0x0501, _)
Expand Down
2 changes: 2 additions & 0 deletions src/modbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
wsa_err = WSAGetLastError();

// no equivalent to ETIMEDOUT when select fails on Windows
// but we still need it to forget the invalid answer
modbus_flush(ctx);
if (wsa_err == WSAENETDOWN || wsa_err == WSAENOTSOCK) {
modbus_close(ctx);
modbus_connect(ctx);
Expand Down
51 changes: 49 additions & 2 deletions tests/unit-test-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ int main(int argc, char *argv[])

memset(last_test_title, 0, sizeof(last_test_title));

#ifdef _WIN32
# ifdef HAVE_SETVBUF
// auto-flush so logs are comprehensible when the
// same console collects output of server and client
// https://stackoverflow.com/a/214292/4715872
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
# endif
#endif

if (argc > 1) {
if (strcmp(argv[1], "tcp") == 0) {
use_backend = TCP;
Expand Down Expand Up @@ -288,6 +298,10 @@ int main(int argc, char *argv[])
: UT_INPUT_REGISTERS_NB;
memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));

/* Wait remaining bytes before flushing */
usleep(1000000);
modbus_flush(ctx);

TEST_TITLE("4/5 modbus_write_and_read_registers");
/* Write registers to zero from tab_rp_registers and store read registers
into tab_rp_registers. So the read registers must set to 0, except the
Expand Down Expand Up @@ -721,13 +735,46 @@ int main(int argc, char *argv[])
/* Wait remaining bytes before flushing */
usleep(11 * 5000);
modbus_flush(ctx);
/* ...and then some, just in case (e.g. kernel delays, clock jitter, multi-CPU...) */
usleep(1000000);
modbus_flush(ctx);

/* Timeout of 7ms between bytes */
TEST_TITLE("2/2 Adapted byte timeout (7ms > 5ms)");
TEST_TITLE("2/2-A Adapted byte timeout (7ms > 5ms)");
modbus_set_byte_timeout(ctx, 0, 7000);
rc = modbus_read_registers(
ctx, UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS, 1, tab_rp_registers);
ASSERT_TRUE(rc == 1, "FAILED (rc: %d != 1)", rc);
if (rc == 1) {
ASSERT_TRUE(rc == 1, "FAILED (rc: %d != 1)", rc);
} else {
/* Timeout of 20ms between bytes, allow for 2*16+1
* Windows sleep seems to be at least 15ms always.
*/
usleep(1000000);
modbus_flush(ctx);
TEST_TITLE("2/2-B Adapted byte timeout (33ms > 20ms)");
modbus_set_byte_timeout(ctx, 0, 33000);
rc = modbus_read_registers(
ctx, UT_REGISTERS_ADDRESS_BYTE_SLEEP_20_MS, 1, tab_rp_registers);

if (rc == 1) {
ASSERT_TRUE(rc == 1, "FAILED (rc: %d != 1)", rc);
} else {
/* For some reason, FreeBSD 12 and OpenBSD 6.5 also
* tended to fail with 7ms and even 33ms variants
* as "gmake check", but passed in
* gmake -j 8 && ( ./tests/unit-test-server|cat & sleep 1 ; ./tests/unit-test-client|cat )
* An even longer timeout seems to satisfy all of them.
*/
usleep(1000000);
modbus_flush(ctx);
TEST_TITLE("2/2-C Adapted byte timeout (66ms > 20ms)");
modbus_set_byte_timeout(ctx, 0, 66000);
rc = modbus_read_registers(
ctx, UT_REGISTERS_ADDRESS_BYTE_SLEEP_20_MS, 1, tab_rp_registers);
ASSERT_TRUE(rc == 1, "FAILED (rc: %d != 1)", rc);
}
}
}

/* Restore original byte timeout */
Expand Down
24 changes: 22 additions & 2 deletions tests/unit-test-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ int main(int argc, char *argv[])
int header_length;
char *ip_or_device = NULL;

#ifdef _WIN32
# ifdef HAVE_SETVBUF
// auto-flush so logs are comprehensible when the
// same console collects output of server and client
// https://stackoverflow.com/a/214292/4715872
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
# endif
#endif

if (argc > 1) {
if (strcmp(argv[1], "tcp") == 0) {
use_backend = TCP;
Expand Down Expand Up @@ -169,6 +179,9 @@ int main(int argc, char *argv[])

for (;;) {
do {
#ifdef _WIN32
fflush(stdout);
#endif
rc = modbus_receive(ctx, query);
/* Filtered queries return 0 */
} while (rc == 0);
Expand Down Expand Up @@ -208,7 +221,7 @@ int main(int argc, char *argv[])
} else if (address == UT_REGISTERS_ADDRESS_SLEEP_500_MS) {
printf("Sleep 0.5 s before replying\n");
usleep(500000);
} else if (address == UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS) {
} else if (address == UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS || address == UT_REGISTERS_ADDRESS_BYTE_SLEEP_20_MS) {
/* Test low level only available in TCP mode */
/* Catch the reply and send reply byte a byte */
uint8_t req[] = "\x00\x1C\x00\x00\x00\x05\xFF\x03\x02\x00\x00";
Expand All @@ -223,7 +236,11 @@ int main(int argc, char *argv[])
req[1] = query[1];
for (i = 0; i < req_length; i++) {
printf("(%.2X)", req[i]);
usleep(5000);
if (address == UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS) {
usleep(5000);
} else if (address == UT_REGISTERS_ADDRESS_BYTE_SLEEP_20_MS) {
usleep(20000);
}
rc = send(w_s, (const char *) (req + i), 1, MSG_NOSIGNAL);
if (rc == -1) {
break;
Expand All @@ -250,6 +267,9 @@ int main(int argc, char *argv[])
}
}

#ifdef _WIN32
fflush(stdout);
#endif
rc = modbus_reply(ctx, query, rc, mb_mapping);
if (rc == -1) {
break;
Expand Down
5 changes: 4 additions & 1 deletion tests/unit-test.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ const uint16_t UT_REGISTERS_ADDRESS_SPECIAL = 0x170;
const uint16_t UT_REGISTERS_ADDRESS_INVALID_TID_OR_SLAVE = 0x171;
/* The server will wait for 1 second before replying to test timeout */
const uint16_t UT_REGISTERS_ADDRESS_SLEEP_500_MS = 0x172;
/* The server will wait for 5 ms before sending each byte */
/* The server will wait for 5 ms before sending each byte
* WARNING: this may be too short for WIN32 */
const uint16_t UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS = 0x173;
/* The server will wait for 20 ms before sending each byte */
const uint16_t UT_REGISTERS_ADDRESS_BYTE_SLEEP_20_MS = 0x174;

/* If the following value is used, a bad response is sent.
It's better to test with a lower value than
Expand Down