diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index f0cb245b76..a5946e6a9d 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -34,6 +34,7 @@ jobs: POLLER: poll - os: ubuntu-latest BUILD_TYPE: android + NDK_VERSION: android-ndk-r25 DRAFT: disabled - os: ubuntu-latest BUILD_TYPE: coverage @@ -148,6 +149,8 @@ jobs: USE_NSS: ${{ matrix.USE_NSS }} VMCI: ${{ matrix.VMCI }} POLLER: ${{ matrix.POLLER }} + NDK_VERSION: ${{ matrix.NDK_VERSION }} + ANDROID_NDK_ROOT: /tmp/${{ matrix.NDK_VERSION }} steps: - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v1.0.2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 36f4876901..5ad2cc106f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -567,12 +567,18 @@ if(ZMQ_HAVE_WINDOWS) # Cannot use check_library_exists because the symbol is always declared as char(*)(void) set(CMAKE_REQUIRED_LIBRARIES "ws2_32.lib") check_cxx_symbol_exists(WSAStartup "winsock2.h" HAVE_WS2_32) + if(HAVE_WS2_32) + set(pkg_config_libs_private "${pkg_config_libs_private} -lws2_32") + endif() set(CMAKE_REQUIRED_LIBRARIES "rpcrt4.lib") check_cxx_symbol_exists(UuidCreateSequential "rpc.h" HAVE_RPCRT4) set(CMAKE_REQUIRED_LIBRARIES "iphlpapi.lib") check_cxx_symbol_exists(GetAdaptersAddresses "winsock2.h;iphlpapi.h" HAVE_IPHLAPI) + if(HAVE_IPHLAPI) + set(pkg_config_libs_private "${pkg_config_libs_private} -liphlpapi") + endif() check_cxx_symbol_exists(if_nametoindex "iphlpapi.h" HAVE_IF_NAMETOINDEX) set(CMAKE_REQUIRED_LIBRARIES "") diff --git a/src/clock.cpp b/src/clock.cpp index fc2151f63b..eeb7a68167 100644 --- a/src/clock.cpp +++ b/src/clock.cpp @@ -223,6 +223,10 @@ uint64_t zmq::clock_t::rdtsc () ((13 & 15) << 3) | // crm ((0 & 7) << 0)); // op2 return _ReadStatusReg (pmccntr_el0); +#elif (defined(_WIN32) && defined(__GNUC__) && defined(__aarch64__)) + uint64_t val; + __asm__ volatile("mrs %0, pmccntr_el0" : "=r"(val)); + return val; #elif (defined __GNUC__ && (defined __i386__ || defined __x86_64__)) uint32_t low, high; __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); diff --git a/src/socket_base.cpp b/src/socket_base.cpp index 5a9adcdeea..c76ff98d97 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -228,7 +228,8 @@ zmq::socket_base_t::socket_base_t (ctx_t *parent_, _monitor_events (0), _thread_safe (thread_safe_), _reaper_signaler (NULL), - _monitor_sync () + _monitor_sync (), + _disconnected (false) { options.socket_id = sid_; options.ipv6 = (parent_->get (ZMQ_IPV6) != 0); diff --git a/tests/test_reconnect_options.cpp b/tests/test_reconnect_options.cpp index af34934b72..43d8cc5afb 100644 --- a/tests/test_reconnect_options.cpp +++ b/tests/test_reconnect_options.cpp @@ -246,6 +246,46 @@ void reconnect_stop_on_handshake_failed () } #endif +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_HAVE_IPC) +// test stopping reconnect after disconnect +void reconnect_stop_after_disconnect () +{ + // Setup sub socket + void *sub = test_context_socket (ZMQ_SUB); + // Monitor all events on sub + TEST_ASSERT_SUCCESS_ERRNO ( + zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL)); + // Create socket for collecting monitor events + void *sub_mon = test_context_socket (ZMQ_PAIR); + // Connect so they'll get events + TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub")); + // Set option to stop reconnecting after disconnect + int stopReconnectAfterDisconnect = ZMQ_RECONNECT_STOP_AFTER_DISCONNECT; + TEST_ASSERT_SUCCESS_ERRNO ( + zmq_setsockopt (sub, ZMQ_RECONNECT_STOP, &stopReconnectAfterDisconnect, + sizeof (stopReconnectAfterDisconnect))); + + // Connect to a dummy that cannot be connected + TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, "ipc://@dummy")); + + // Confirm that connect failed and reconnect + expect_monitor_event (sub_mon, ZMQ_EVENT_CLOSED); + expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_RETRIED); + + // Disconnect the sub socket + TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sub, "ipc://@dummy")); + + // Confirm that connect failed and will not reconnect + expect_monitor_event (sub_mon, ZMQ_EVENT_CLOSED); + + // Close sub + test_context_socket_close_zero_linger (sub); + + // Close monitor + test_context_socket_close_zero_linger (sub_mon); +} +#endif + void setUp () { setup_test_context (); @@ -267,6 +307,9 @@ int main (void) #ifdef ZMQ_BUILD_DRAFT_API RUN_TEST (reconnect_stop_on_refused); RUN_TEST (reconnect_stop_on_handshake_failed); +#endif +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_HAVE_IPC) + RUN_TEST (reconnect_stop_after_disconnect); #endif return UNITY_END (); }