From f1d2f390318f4c8460e9a4887e8461a58b3b8526 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 31 Jan 2021 16:20:16 +0100 Subject: [PATCH] Added signal-safe sleep function which does not return when a timer signal happens. Fixes some random fails in the test suite. --- src/tl/tl/tl.pro | 2 + src/tl/tl/tlSleep.cc | 95 +++++++++++++++++++++ src/tl/tl/tlSleep.h | 45 ++++++++++ src/tl/unit_tests/tlThreadedWorkersTests.cc | 27 ++---- src/tl/unit_tests/tlThreadsTests.cc | 13 +-- 5 files changed, 153 insertions(+), 29 deletions(-) create mode 100644 src/tl/tl/tlSleep.cc create mode 100644 src/tl/tl/tlSleep.h diff --git a/src/tl/tl/tl.pro b/src/tl/tl/tl.pro index 9e003fe27..0b1d91ead 100644 --- a/src/tl/tl/tl.pro +++ b/src/tl/tl/tl.pro @@ -27,6 +27,7 @@ SOURCES = \ tlObject.cc \ tlProgress.cc \ tlScriptError.cc \ + tlSleep.cc \ tlStaticObjects.cc \ tlStream.cc \ tlString.cc \ @@ -77,6 +78,7 @@ HEADERS = \ tlProgress.h \ tlReuseVector.h \ tlScriptError.h \ + tlSleep.h \ tlStableVector.h \ tlStaticObjects.h \ tlStream.h \ diff --git a/src/tl/tl/tlSleep.cc b/src/tl/tl/tlSleep.cc new file mode 100644 index 000000000..124047344 --- /dev/null +++ b/src/tl/tl/tlSleep.cc @@ -0,0 +1,95 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "tlSleep.h" + +#if defined(_MSC_VER) || defined(_WIN32) +# include +#else +# include +# include +# include +# include +#endif + +#include + +namespace tl +{ + +static void init_sigmask_for_sleep (sigset_t *mask) +{ + sigemptyset (mask); + // disable a couple of signals we don't want to interfere with our sleep + sigaddset (mask, SIGCHLD); + sigaddset (mask, SIGALRM); + sigaddset (mask, SIGVTALRM); + sigaddset (mask, SIGPROF); + sigaddset (mask, SIGWINCH); +} + +void usleep (unsigned long us) +{ +#if defined(_WIN32) + + Sleep ((DWORD) ((us + 999) / 1000)); + +#else + + // Portable sleep for platforms other than Windows. + + struct timespec wait; + wait.tv_sec = (us / 1000000ul); + wait.tv_nsec = (us % 1000000ul) * 1000ul; + + sigset_t mask; + init_sigmask_for_sleep (&mask); + + pselect (0, NULL, NULL, NULL, &wait, &mask); + +#endif +} + +void msleep (unsigned long ms) +{ +#if defined(_WIN32) + + Sleep ((DWORD) ms); + +#else + + // Portable sleep for platforms other than Windows. + + struct timespec wait; + wait.tv_sec = (ms / 1000ul); + wait.tv_nsec = (ms % 1000ul) * 1000000ul; + + sigset_t mask; + init_sigmask_for_sleep (&mask); + + pselect (0, NULL, NULL, NULL, &wait, &mask); + +#endif +} + +} + diff --git a/src/tl/tl/tlSleep.h b/src/tl/tl/tlSleep.h new file mode 100644 index 000000000..b362b173b --- /dev/null +++ b/src/tl/tl/tlSleep.h @@ -0,0 +1,45 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2021 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_tlSleep +#define HDR_tlSleep + +#include "tlCommon.h" + +namespace tl +{ + +/** + * @brief Sleeps the given number of microseconds + */ +TL_PUBLIC void usleep (unsigned long us); + +/** + * @brief Slees the given number of milliseconds + */ +TL_PUBLIC void msleep (unsigned long ms); + +} // namespace tl + +#endif + diff --git a/src/tl/unit_tests/tlThreadedWorkersTests.cc b/src/tl/unit_tests/tlThreadedWorkersTests.cc index 6e5f5ebbf..f1fa5d646 100644 --- a/src/tl/unit_tests/tlThreadedWorkersTests.cc +++ b/src/tl/unit_tests/tlThreadedWorkersTests.cc @@ -26,19 +26,10 @@ #include "tlTimer.h" #include "tlUnitTest.h" #include "tlThreads.h" +#include "tlSleep.h" #include -#if defined(WIN32) -#include -inline void usleep(long us) -{ - Sleep(us / 1000); -} -#else -#include -#endif - class Sum { public: @@ -178,7 +169,7 @@ TEST(2) job.start (); - usleep (2000000); + tl::usleep (2000000); EXPECT_EQ (s_sum[0].sum (), 10000000); } @@ -229,7 +220,7 @@ TEST(5) job.start (); - usleep (100000); + tl::usleep (100000); job.terminate (); EXPECT_EQ (s_sum[0].sum () < 10000000, true); @@ -250,7 +241,7 @@ TEST(10) job.start (); - usleep (2000000); + tl::usleep (2000000); EXPECT_EQ (s_sum[0].sum () > 0, true); EXPECT_EQ (s_sum[1].sum () > 0, true); @@ -361,7 +352,7 @@ void run_thread_tests (tl::TestBase *_this, int wait) } job.start (); - usleep (wait); + tl::usleep (wait); job.terminate (); EXPECT_EQ (job.is_running (), false); @@ -449,7 +440,7 @@ TEST(22) job.start (); while (!s_sum[0].flag () || !s_sum[1].flag () || !s_sum[2].flag () || !s_sum[3].flag ()) { - usleep (10000); + tl::usleep (10000); } job.stop (); EXPECT_EQ (job.is_running (), false); @@ -477,7 +468,7 @@ TEST(23) job.start (); while (!s_sum[0].flag () || !s_sum[1].flag ()) { - usleep (10000); + tl::usleep (10000); } job.stop (); EXPECT_EQ (job.is_running (), false); @@ -505,7 +496,7 @@ TEST(24) job.start (); while (!s_sum[0].flag () && !s_sum[1].flag () && !s_sum[2].flag () && !s_sum[3].flag ()) { - usleep (10000); + tl::usleep (10000); } job.stop (); EXPECT_EQ (job.is_running (), false); @@ -533,7 +524,7 @@ TEST(25) job.start (); while (!s_sum[0].flag () && !s_sum[1].flag ()) { - usleep (10000); + tl::usleep (10000); } job.stop (); EXPECT_EQ (job.is_running (), false); diff --git a/src/tl/unit_tests/tlThreadsTests.cc b/src/tl/unit_tests/tlThreadsTests.cc index b4de410e9..50e0d0f00 100644 --- a/src/tl/unit_tests/tlThreadsTests.cc +++ b/src/tl/unit_tests/tlThreadsTests.cc @@ -22,19 +22,10 @@ #include "tlThreads.h" #include "tlUnitTest.h" +#include "tlSleep.h" #include -#if defined(WIN32) -#include -inline void usleep(long us) -{ - Sleep(us / 1000); -} -#else -#include -#endif - class MyThread : public tl::Thread { public: @@ -59,7 +50,7 @@ public: tl::MutexLocker locker (&m_lock); ++m_value; } - usleep (10000); + tl::usleep (10000); } }