From 8e4f37d62405bc069e3576307e47fac3981223b7 Mon Sep 17 00:00:00 2001 From: oko256 <139907514+oko256@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:24:37 +0300 Subject: [PATCH 1/2] zsock: Check native socket in zsock_resolve before ZMQ socket Especially in Windows (at least on builds using MSVC), `zsock_resolve` randomly (but quite often) segfaults if the passed pointer is actually pointing to a native `SOCKET` instead of zactor, zsock, or a ZMQ socket. This happens because `zmq_getsockopt` tries to check if, after casting, the pointer points to an object with specific tag (`check_tag()`). Unfortunately, reading this area of memory is often an access violation if the pointer actually pointed to a `SOCKET` (which is a smaller data type). It seems that checking if the pointer is to a native socket first before checking if it is a ZMQ socket fixes this, so these checks were reordered. Resolves #2300 --- src/zsock.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/zsock.c b/src/zsock.c index 3eaf1bc7b..c4d14ab20 100644 --- a/src/zsock.c +++ b/src/zsock.c @@ -1845,13 +1845,10 @@ zsock_resolve (void *self) if (zsock_is (self)) return ((zsock_t *) self)->handle; - // Check if we have a valid ZMQ socket by probing the socket type - int type; - size_t option_len = sizeof (int); - if (zmq_getsockopt (self, ZMQ_TYPE, &type, &option_len) == 0) - return self; - // Check if self is a valid FD or socket FD + // We need to check this before zmq_getsockopt, because tag check may + // cause a segfault if we are checking a native SOCKET (since the data + // type is smaller than the full object). // TODO: this code should move to zsys_isfd () as we don't like // non-portable code outside of that class. int sock_type = -1; @@ -1866,6 +1863,13 @@ zsock_resolve (void *self) if (rc == 0 || (rc == -1 && errno == ENOTSOCK)) return NULL; // It's a socket FD or FD #endif + + // Check if we have a valid ZMQ socket by probing the socket type + int type; + size_t option_len = sizeof (int); + if (zmq_getsockopt (self, ZMQ_TYPE, &type, &option_len) == 0) + return self; + // Socket appears to be something else, return it as-is return self; } From b69dc029f79a6a550a40913db950a3440259fd85 Mon Sep 17 00:00:00 2001 From: oko256 <139907514+oko256@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:33:08 +0300 Subject: [PATCH 2/2] ztimerset: Make selftest more reliable On Windows, the `Sleep()` function resolution (which is used by `zclock_sleep()`) can typically be as bad as 16 ms. This caused the selftest to randomly fail because it waited exactly the remaining time to the timer expiration before asserting the result. Made this more reliable by adding some margin to the sleep. --- src/ztimerset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ztimerset.c b/src/ztimerset.c index 1db38e0b1..498f61caf 100644 --- a/src/ztimerset.c +++ b/src/ztimerset.c @@ -181,7 +181,7 @@ ztimerset_test (bool verbose) assert (!timer_invoked); int timeout = ztimerset_timeout (self); assert (timeout > 0); - zclock_sleep (timeout); + zclock_sleep (timeout + 20); rc = ztimerset_execute (self); assert (rc == 0); assert (timer_invoked);