fixes #446 efd_win.inc global critical section should be mutex
fixes #485 Windows efd_init should not assert on failure
fixes #484 Make tcp_shutdown a little less likely to hang forever
fixes #483 CMake tests hang forever
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f46fc56..a575468 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,7 @@
add_executable (${NAME} tests/${NAME}.c)
target_link_libraries (${NAME} nanomsg)
add_test (NAME ${NAME} COMMAND ${NAME})
+ set_tests_properties (${NAME} PROPERTIES TIMEOUT 30)
endmacro (add_libnanomsg_test)
# Transport tests.
diff --git a/src/utils/efd_win.inc b/src/utils/efd_win.inc
index 8d25340..4978c76 100644
--- a/src/utils/efd_win.inc
+++ b/src/utils/efd_win.inc
@@ -56,15 +56,24 @@
/* This function has to be enclosed in a system-wide critical section
so that two instances of the library don't accidentally create an efd
- crossing the process boundary.
- CAUTION: This critical section has machine-wide scope. Thus, it must
- be properly exited even before crashing the process by an assertion. */
- sync = CreateEvent (&sa, FALSE, TRUE, "Global\\nanomsg-port-sync");
+ crossing the process boundary. */
+ sync = CreateMutex (&sa, FALSE, "Global\\nanomsg-port-mutex");
win_assert (sync != NULL);
- /* Enter the critical section. */
- dwrc = WaitForSingleObject (sync, INFINITE);
- nn_assert (dwrc == WAIT_OBJECT_0);
+ /* Enter the critical section. If we cannot get the object in 10 seconds
+ then something is seriously wrong. Just bail. */
+ dwrc = WaitForSingleObject (sync, 10000);
+ switch (dwrc) {
+ case WAIT_ABANDONED:
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_TIMEOUT:
+ rc = ETIMEDOUT;
+ goto wsafail3;
+ default:
+ rc = nn_err_wsa_to_posix (WSAGetLastError ());
+ goto wsafail3;
+ }
/* Unfortunately, on Windows the only way to send signal to a file
descriptor (SOCKET) is to create a full-blown TCP connecting on top of
@@ -141,7 +150,7 @@
if (i == NN_EFD_RETRIES)
goto wsafail2;
- while (1) {
+ for (;;) {
/* Accept new incoming connection. */
addrlen = sizeof (addr);
@@ -166,7 +175,7 @@
goto wsafail;
/* Leave the critical section. */
- brc = SetEvent (sync);
+ brc = ReleaseMutex (sync);
win_assert (brc != 0);
brc = CloseHandle (sync);
win_assert (brc != 0);
@@ -184,11 +193,11 @@
wsafail:
rc = nn_err_wsa_to_posix (WSAGetLastError ());
wsafail2:
- brc = SetEvent (sync);
+ brc = ReleaseMutex (sync);
win_assert (brc != 0);
+wsafail3:
brc = CloseHandle (sync);
win_assert (brc != 0);
- errnum_assert (0, rc);
return -rc;
}
diff --git a/tests/tcp_shutdown.c b/tests/tcp_shutdown.c
index bd28ef9..24339aa 100644
--- a/tests/tcp_shutdown.c
+++ b/tests/tcp_shutdown.c
@@ -57,13 +57,19 @@
{
int s;
int i;
+ int ms;
s = test_socket (AF_SP, NN_PULL);
- for (i = 0; i < 10; ++i) {
+ /* On AppVeyor/Windows, if this is 10, we get timeouts trying to
+ establish the connection. This value (5) seems to work though. */
+ for (i = 0; i < 5; ++i) {
test_connect (s, SOCKET_ADDRESS);
}
+ ms = 2000;
+ test_setsockopt (s, NN_SOL_SOCKET, NN_RCVTIMEO, &ms, sizeof (ms));
+
for (i = 0; i < MESSAGES_PER_THREAD; ++i) {
test_recv (s, "hello");
}
@@ -91,8 +97,9 @@
for (j = 0; j != TEST_LOOPS; ++j) {
for (i = 0; i != THREAD_COUNT; ++i)
nn_thread_init (&threads [i], routine, NULL);
- for (i = 0; i != THREAD_COUNT; ++i)
+ for (i = 0; i != THREAD_COUNT; ++i) {
nn_thread_term (&threads [i]);
+ }
}
test_close (sb);
@@ -103,10 +110,13 @@
test_bind (sb, SOCKET_ADDRESS);
for (j = 0; j != TEST_LOOPS; ++j) {
+ int ms;
for (i = 0; i != TEST2_THREAD_COUNT; ++i)
- nn_thread_init (&threads [i], routine2, NULL);
+ nn_thread_init (&threads [i], routine2, &threads[i]);
nn_atomic_init(&active, TEST2_THREAD_COUNT);
+ ms = 2000;
+ test_setsockopt (sb, NN_SOL_SOCKET, NN_SNDTIMEO, &ms, sizeof (ms));
while (active.n) {
(void) nn_send (sb, "hello", 5, NN_DONTWAIT);
}
diff --git a/tests/testutil.h b/tests/testutil.h
index fe6aba1..89e5247 100644
--- a/tests/testutil.h
+++ b/tests/testutil.h
@@ -33,6 +33,8 @@
static void test_close_impl (char *file, int line, int sock);
static void test_send_impl (char *file, int line, int sock, char *data);
static void test_recv_impl (char *file, int line, int sock, char *data);
+static int test_setsockopt_impl (char *file, int line, int sock, int level,
+ int option, const void *optval, size_t optlen);
#define test_socket(f, p) test_socket_impl (__FILE__, __LINE__, (f), (p))
#define test_connect(s, a) test_connect_impl (__FILE__, __LINE__, (s), (a))
@@ -40,6 +42,8 @@
#define test_send(s, d) test_send_impl (__FILE__, __LINE__, (s), (d))
#define test_recv(s, d) test_recv_impl (__FILE__, __LINE__, (s), (d))
#define test_close(s) test_close_impl (__FILE__, __LINE__, (s))
+#define test_setsockopt(s, l, o, v, z) test_setsockopt_impl (__FILE__, \
+ __LINE__, (s), (l), (o), (v), (z))
static int NN_UNUSED test_socket_impl (char *file, int line, int family,
int protocol)
@@ -89,6 +93,22 @@
return rc;
}
+static int NN_UNUSED test_setsockopt_impl (char *file, int line,
+ int sock, int level, int option, const void *optval, size_t optlen)
+{
+ int rc;
+
+ rc = nn_setsockopt (sock, level, option, optval, optlen);
+ if(rc < 0) {
+ fprintf (stderr, "Failed set option \"%d\": %s [%d] (%s:%d)\n",
+ option,
+ nn_err_strerror (errno),
+ (int) errno, file, line);
+ nn_err_abort ();
+ }
+ return rc;
+}
+
static void NN_UNUSED test_close_impl (char *file, int line, int sock)
{
int rc;