From 886d8db70750296559b79e73e728214963ebb4a8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 2 Aug 2017 18:42:48 +0200 Subject: [PATCH 1/3] Comment about system timer resolutions that can matter for "sleep until zsys_file_stable_age_msec() threshold has effect" --- src/zsys.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/zsys.c b/src/zsys.c index 575d39134..96f3a13d1 100644 --- a/src/zsys.c +++ b/src/zsys.c @@ -1511,6 +1511,13 @@ void // This can be used in code that chooses to wait for this timeout // before testing if a filesystem object is "stable" or not. +// Note that the OS timer quantization can bite you, so it may be +// reasonably safe to sleep/wait/poll for a larger timeout before +// assuming a fault, e.g. the default timer resolution on Windows +// is 15.6 ms (per timer interrupt 64 times a second), graphed here: +// https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx +// and Unix/Linux OSes also have different-resolution timers. + int64_t zsys_file_stable_age_msec (void) { From e4331adc7b3a5a5dd42521d9f962aed02bba601a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2017 12:17:23 +0200 Subject: [PATCH 2/3] test.py : when using default file_stable_age_msec(), do not forget to increment expectations --- bindings/python/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/test.py b/bindings/python/test.py index ab40b3459..3ff98886b 100644 --- a/bindings/python/test.py +++ b/bindings/python/test.py @@ -57,7 +57,7 @@ def test_zdir(self): initfile.close() try: - stable_age = float(file_stable_age_msec()) / 1000.0 + stable_age = float(file_stable_age_msec()) / 1000.0 + 0.001 except Exception: stable_age = 3.001 time.sleep(stable_age) # wait for initial file to become 'stable' @@ -190,7 +190,7 @@ def test_zfile(self): del f try: - stable_age = float(file_stable_age_msec()) / 1000.0 + stable_age = float(file_stable_age_msec()) / 1000.0 + 0.001 except Exception: stable_age = 3.001 From c14fd5e86609d9c835d21dd5738c2f03a6d4751e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Thu, 3 Aug 2017 12:18:24 +0200 Subject: [PATCH 3/3] test.py : default file_stable_age_msec to 5000, and use longer polls than sleeps in tests --- api/zsys.api | 2 +- bindings/jni/src/main/java/org/zeromq/czmq/Zsys.java | 2 +- bindings/lua_ffi/czmq_ffi.lua | 2 +- bindings/nodejs/README.md | 2 +- bindings/python/czmq/_czmq_ctypes.py | 2 +- bindings/python/test.py | 8 ++++---- bindings/python_cffi/czmq_cffi/_cdefs.inc | 2 +- bindings/python_cffi/czmq_cffi/cdefs.py | 2 +- bindings/qml/src/QmlZsys.cpp | 2 +- bindings/qml/src/QmlZsys.h | 2 +- bindings/qt/src/qzsys.cpp | 2 +- bindings/qt/src/qzsys.h | 2 +- bindings/ruby/lib/czmq/ffi/zsys.rb | 2 +- include/zsys.h | 2 +- src/czmq_classes.h | 2 +- src/zdir.c | 12 ++++++------ src/zfile.c | 4 ++-- src/zsys.c | 8 ++++---- 18 files changed, 30 insertions(+), 30 deletions(-) diff --git a/api/zsys.api b/api/zsys.api index 77623982c..07a93cf23 100644 --- a/api/zsys.api +++ b/api/zsys.api @@ -308,7 +308,7 @@ that should elapse until we consider that object "stable" at the current zclock_time() moment. The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c - which generally depends on host OS, with fallback value of 3000. + which generally depends on host OS, with fallback value of 5000. diff --git a/bindings/jni/src/main/java/org/zeromq/czmq/Zsys.java b/bindings/jni/src/main/java/org/zeromq/czmq/Zsys.java index 349372e9b..6a8722354 100644 --- a/bindings/jni/src/main/java/org/zeromq/czmq/Zsys.java +++ b/bindings/jni/src/main/java/org/zeromq/czmq/Zsys.java @@ -301,7 +301,7 @@ public int maxMsgsz () { that should elapse until we consider that object "stable" at the current zclock_time() moment. The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c - which generally depends on host OS, with fallback value of 3000. + which generally depends on host OS, with fallback value of 5000. */ native static void __setFileStableAgeMsec (long fileStableAgeMsec); public void setFileStableAgeMsec (long fileStableAgeMsec) { diff --git a/bindings/lua_ffi/czmq_ffi.lua b/bindings/lua_ffi/czmq_ffi.lua index 7400ab876..e14e89956 100644 --- a/bindings/lua_ffi/czmq_ffi.lua +++ b/bindings/lua_ffi/czmq_ffi.lua @@ -3722,7 +3722,7 @@ int // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. void zsys_set_file_stable_age_msec (int64_t file_stable_age_msec); diff --git a/bindings/nodejs/README.md b/bindings/nodejs/README.md index 3f4edd5c7..40cda6ae5 100644 --- a/bindings/nodejs/README.md +++ b/bindings/nodejs/README.md @@ -3922,7 +3922,7 @@ Configure the threshold value of filesystem object age per st_mtime that should elapse until we consider that object "stable" at the current zclock_time() moment. The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -which generally depends on host OS, with fallback value of 3000. +which generally depends on host OS, with fallback value of 5000. ``` msecs my_zsys.fileStableAgeMsec () diff --git a/bindings/python/czmq/_czmq_ctypes.py b/bindings/python/czmq/_czmq_ctypes.py index 9a74b3ef3..895684ef6 100644 --- a/bindings/python/czmq/_czmq_ctypes.py +++ b/bindings/python/czmq/_czmq_ctypes.py @@ -7624,7 +7624,7 @@ def set_file_stable_age_msec(file_stable_age_msec): that should elapse until we consider that object "stable" at the current zclock_time() moment. The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -which generally depends on host OS, with fallback value of 3000. +which generally depends on host OS, with fallback value of 5000. """ return lib.zsys_set_file_stable_age_msec(file_stable_age_msec) diff --git a/bindings/python/test.py b/bindings/python/test.py index 3ff98886b..ab27dc721 100644 --- a/bindings/python/test.py +++ b/bindings/python/test.py @@ -57,9 +57,9 @@ def test_zdir(self): initfile.close() try: - stable_age = float(file_stable_age_msec()) / 1000.0 + 0.001 + stable_age = float(file_stable_age_msec()) / 1000.0 + 0.050 except Exception: - stable_age = 3.001 + stable_age = 5.050 time.sleep(stable_age) # wait for initial file to become 'stable' watch.sock().send(b"si", b"TIMEOUT", 100) @@ -190,9 +190,9 @@ def test_zfile(self): del f try: - stable_age = float(file_stable_age_msec()) / 1000.0 + 0.001 + stable_age = float(file_stable_age_msec()) / 1000.0 + 0.050 except Exception: - stable_age = 3.001 + stable_age = 5.050 self.assertTrue(file.has_changed()) self.assertFalse(file.is_stable()) diff --git a/bindings/python_cffi/czmq_cffi/_cdefs.inc b/bindings/python_cffi/czmq_cffi/_cdefs.inc index 98747aca1..d51696600 100644 --- a/bindings/python_cffi/czmq_cffi/_cdefs.inc +++ b/bindings/python_cffi/czmq_cffi/_cdefs.inc @@ -3727,7 +3727,7 @@ int // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. void zsys_set_file_stable_age_msec (int64_t file_stable_age_msec); diff --git a/bindings/python_cffi/czmq_cffi/cdefs.py b/bindings/python_cffi/czmq_cffi/cdefs.py index 84b7a62fd..31e542528 100644 --- a/bindings/python_cffi/czmq_cffi/cdefs.py +++ b/bindings/python_cffi/czmq_cffi/cdefs.py @@ -3729,7 +3729,7 @@ // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. void zsys_set_file_stable_age_msec (int64_t file_stable_age_msec); diff --git a/bindings/qml/src/QmlZsys.cpp b/bindings/qml/src/QmlZsys.cpp index f8a5abd7a..ad6014056 100644 --- a/bindings/qml/src/QmlZsys.cpp +++ b/bindings/qml/src/QmlZsys.cpp @@ -321,7 +321,7 @@ int QmlZsysAttached::maxMsgsz () { // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. void QmlZsysAttached::setFileStableAgeMsec (int64_t fileStableAgeMsec) { zsys_set_file_stable_age_msec (fileStableAgeMsec); }; diff --git a/bindings/qml/src/QmlZsys.h b/bindings/qml/src/QmlZsys.h index 8ff5379e8..f1f2362b7 100644 --- a/bindings/qml/src/QmlZsys.h +++ b/bindings/qml/src/QmlZsys.h @@ -228,7 +228,7 @@ public slots: // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c - // which generally depends on host OS, with fallback value of 3000. + // which generally depends on host OS, with fallback value of 5000. void setFileStableAgeMsec (int64_t fileStableAgeMsec); // Return current threshold value of file stable age in msec. diff --git a/bindings/qt/src/qzsys.cpp b/bindings/qt/src/qzsys.cpp index 625602c01..397b6ab56 100644 --- a/bindings/qt/src/qzsys.cpp +++ b/bindings/qt/src/qzsys.cpp @@ -367,7 +367,7 @@ int QZsys::maxMsgsz () // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. void QZsys::setFileStableAgeMsec (int64_t fileStableAgeMsec) { zsys_set_file_stable_age_msec (fileStableAgeMsec); diff --git a/bindings/qt/src/qzsys.h b/bindings/qt/src/qzsys.h index 1292c1208..545028da8 100644 --- a/bindings/qt/src/qzsys.h +++ b/bindings/qt/src/qzsys.h @@ -193,7 +193,7 @@ class QT_CZMQ_EXPORT QZsys : public QObject // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c - // which generally depends on host OS, with fallback value of 3000. + // which generally depends on host OS, with fallback value of 5000. static void setFileStableAgeMsec (int64_t fileStableAgeMsec); // Return current threshold value of file stable age in msec. diff --git a/bindings/ruby/lib/czmq/ffi/zsys.rb b/bindings/ruby/lib/czmq/ffi/zsys.rb index 9d14617a7..3ca031599 100644 --- a/bindings/ruby/lib/czmq/ffi/zsys.rb +++ b/bindings/ruby/lib/czmq/ffi/zsys.rb @@ -527,7 +527,7 @@ def self.max_msgsz() # that should elapse until we consider that object "stable" at the # current zclock_time() moment. # The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c - # which generally depends on host OS, with fallback value of 3000. + # which generally depends on host OS, with fallback value of 5000. # # @param file_stable_age_msec [::FFI::Pointer, #to_ptr] # @return [void] diff --git a/include/zsys.h b/include/zsys.h index 39f1049e3..63ac2bd7f 100644 --- a/include/zsys.h +++ b/include/zsys.h @@ -408,7 +408,7 @@ CZMQ_EXPORT void // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. CZMQ_EXPORT void zsys_set_file_stable_age_msec (int64_t file_stable_age_msec); diff --git a/src/czmq_classes.h b/src/czmq_classes.h index d5a43a190..0b2363fe7 100644 --- a/src/czmq_classes.h +++ b/src/czmq_classes.h @@ -232,7 +232,7 @@ CZMQ_PRIVATE char * // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. CZMQ_PRIVATE void zsys_set_file_stable_age_msec (int64_t file_stable_age_msec); diff --git a/src/zdir.c b/src/zdir.c index 323dc093c..8a90d4fc0 100644 --- a/src/zdir.c +++ b/src/zdir.c @@ -973,9 +973,9 @@ zdir_test (bool verbose) // wait for initial file to become 'stable' #ifdef CZMQ_BUILD_DRAFT_API - zclock_sleep (zsys_file_stable_age_msec() + 1); + zclock_sleep (zsys_file_stable_age_msec() + 50); #else - zclock_sleep (3001); + zclock_sleep (5050); #endif zsock_send (watch, "si", "TIMEOUT", 100); @@ -1004,9 +1004,9 @@ zdir_test (bool verbose) // poll for a certain timeout before giving up and failing the test void* polled = NULL; #ifdef CZMQ_BUILD_DRAFT_API - polled = zpoller_wait(watch_poll, zsys_file_stable_age_msec() + 1); + polled = zpoller_wait(watch_poll, zsys_file_stable_age_msec() + 150); #else - polled = zpoller_wait(watch_poll, 3001); + polled = zpoller_wait(watch_poll, 5150); #endif assert (polled == watch); @@ -1035,9 +1035,9 @@ zdir_test (bool verbose) // poll for a certain timeout before giving up and failing the test. #ifdef CZMQ_BUILD_DRAFT_API - polled = zpoller_wait(watch_poll, zsys_file_stable_age_msec() + 1); + polled = zpoller_wait(watch_poll, zsys_file_stable_age_msec() + 150); #else - polled = zpoller_wait(watch_poll, 3001); + polled = zpoller_wait(watch_poll, 5150); #endif assert (polled == watch); diff --git a/src/zfile.c b/src/zfile.c index e3c6da94d..8732735a6 100644 --- a/src/zfile.c +++ b/src/zfile.c @@ -712,9 +712,9 @@ zfile_test (bool verbose) close (handle); assert (zfile_has_changed (file)); #ifdef CZMQ_BUILD_DRAFT_API - zclock_sleep (zsys_file_stable_age_msec() + 1); + zclock_sleep (zsys_file_stable_age_msec() + 50); #else - zclock_sleep (3001); + zclock_sleep (5050); #endif assert (zfile_has_changed (file)); diff --git a/src/zsys.c b/src/zsys.c index 96f3a13d1..f1fe3a020 100644 --- a/src/zsys.c +++ b/src/zsys.c @@ -67,7 +67,7 @@ static bool s_initialized = false; // This is a private tunable that is likely to be replaced or tweaked later // per comment block at s_zsys_file_stable() implementation, to reflect // the best stat data granularity available on host OS *and* used by czmq. -#define S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC 3000 +#define S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC 5000 #endif // Default globals for new sockets and other joys; these can all be set @@ -78,7 +78,7 @@ static int s_thread_priority = -1; // ZSYS_THREAD_PRIORITY=-1 static size_t s_max_sockets = 1024; // ZSYS_MAX_SOCKETS=1024 static int s_max_msgsz = INT_MAX; // ZSYS_MAX_MSGSZ=INT_MAX static int s_file_stable_age_msec = S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC; - // ZSYS_FILE_STABLE_AGE_MSEC=3000 + // ZSYS_FILE_STABLE_AGE_MSEC=5000 static size_t s_linger = 0; // ZSYS_LINGER=0 static size_t s_sndhwm = 1000; // ZSYS_SNDHWM=1000 static size_t s_rcvhwm = 1000; // ZSYS_RCVHWM=1000 @@ -720,7 +720,7 @@ s_zsys_file_stable (const char *filename, bool verbose) // removable media, and only account even seconds in stat data. // Solutions are two-fold: when using stat fields that are precise // to a second (or inpredictably two), we should actually check for - // (age > 3000) in rounded-microsecond accounting. Also, for some + // (age > 3000+) in rounded-microsecond accounting. Also, for some // systems we can have `configure`-time checks on presence of more // precise (and less standardized) stat timestamp fields, where we // can presumably avoid rounding to thousands and use (age > 2000). @@ -1491,7 +1491,7 @@ zsys_max_msgsz (void) // that should elapse until we consider that object "stable" at the // current zclock_time() moment. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c -// which generally depends on host OS, with fallback value of 3000. +// which generally depends on host OS, with fallback value of 5000. void zsys_set_file_stable_age_msec (int64_t file_stable_age_msec)