diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 291024eb47..ef5b53d51e 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -56,6 +56,7 @@ #include #include #include +#include /* sigprocmask */ #endif // Windows API. Some parts used even on cygwin. @@ -3546,7 +3547,34 @@ void SystemTools::Delay(unsigned int msec) #ifdef _WIN32 Sleep(msec); #else - usleep(msec * 1000); + // Block signals to make sure the entire sleep duration occurs. If + // a signal were to arrive the sleep or usleep might return early + // and there is no way to accurately know how much time was really + // slept without setting up timers. + sigset_t newset; + sigset_t oldset; + sigfillset(&newset); + sigprocmask(SIG_BLOCK, &newset, &oldset); + + // The sleep function gives 1 second resolution and the usleep + // function gives 1e-6 second resolution but on some platforms has a + // maximum sleep time of 1 second. This could be re-implemented to + // use select with masked signals or pselect to mask signals + // atomically. If select is given empty sets and zero as the max + // file descriptor but a non-zero timeout it can be used to block + // for a precise amount of time. + if(msec >= 1000) + { + sleep(msec / 1000); + usleep((msec % 1000) * 1000); + } + else + { + usleep(msec * 1000); + } + + // Restore the signal mask to the previous setting. + sigprocmask(SIG_SETMASK, &oldset, 0); #endif }