Added signal-safe sleep function which does not return when a timer signal happens. Fixes some random fails in the test suite.

This commit is contained in:
Matthias Koefferlein 2021-01-31 16:20:16 +01:00
parent 290d393126
commit f1d2f39031
5 changed files with 153 additions and 29 deletions

View File

@ -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 \

95
src/tl/tl/tlSleep.cc Normal file
View File

@ -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 <Synchapi.h>
#else
# include <unistd.h>
# include <signal.h>
# include <sys/time.h>
# include <sys/select.h>
#endif
#include <stdio.h>
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
}
}

45
src/tl/tl/tlSleep.h Normal file
View File

@ -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

View File

@ -26,19 +26,10 @@
#include "tlTimer.h"
#include "tlUnitTest.h"
#include "tlThreads.h"
#include "tlSleep.h"
#include <stdio.h>
#if defined(WIN32)
#include <windows.h>
inline void usleep(long us)
{
Sleep(us / 1000);
}
#else
#include <unistd.h>
#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);

View File

@ -22,19 +22,10 @@
#include "tlThreads.h"
#include "tlUnitTest.h"
#include "tlSleep.h"
#include <stdio.h>
#if defined(WIN32)
#include <Windows.h>
inline void usleep(long us)
{
Sleep(us / 1000);
}
#else
#include <unistd.h>
#endif
class MyThread : public tl::Thread
{
public:
@ -59,7 +50,7 @@ public:
tl::MutexLocker locker (&m_lock);
++m_value;
}
usleep (10000);
tl::usleep (10000);
}
}