#include #include #include #include #include #include #include #include #include #if defined NDEBUG #define VERIFY(e) do { (e); } while (0) #else #define VERIFY(e) do { assert(e); } while (0) #endif static pthread_mutex_t s_Mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t s_Cond = PTHREAD_COND_INITIALIZER; static void EmptySignalHandler(int) { } static void* ThreadEntry(void*) { // Let the main thread know that the created thread started. VERIFY(pthread_mutex_lock(&s_Mutex) == 0); VERIFY(pthread_cond_signal(&s_Cond) == 0); VERIFY(pthread_mutex_unlock(&s_Mutex) == 0); // Wait until this thread is interrupted by pthread_kill(). timeval tvDelay = { 1000, 0 }; int const iResult = select(0, 0, 0, 0, &tvDelay); assert(iResult < 0 && errno == EINTR); return 0; } int main() { // Make sure that SIGALRM does not terminate the process. struct sigaction SA; memset(&SA, 0, sizeof(SA)); SA.sa_handler = &EmptySignalHandler; sigemptyset(&SA.sa_mask); sigaction(SIGALRM, &SA, 0); // Create a thread. pthread_t TID = 0; VERIFY(pthread_mutex_lock(&s_Mutex) == 0); VERIFY(pthread_create(&TID, 0, ThreadEntry, 0) == 0); assert(TID != 0); VERIFY(pthread_cond_wait(&s_Cond, &s_Mutex) == 0); // Delay for 300 ms, in order to ensure that the thread is inside select() // when pthread_kill() is called from this thread. timeval tvDelay; tvDelay.tv_sec = 0; tvDelay.tv_usec = 300 * 1000; VERIFY(select(0, 0, 0, 0, &tvDelay) == 0); // Query the wall clock time before calling select(). timeval tvStart; gettimeofday(&tvStart, 0); // Interrupt any OS call the thread is doing by sending SIGALRM to it. VERIFY(pthread_kill(TID, SIGALRM) == 0); // Call select() with a timeout of 1s. tvDelay.tv_sec = 1; tvDelay.tv_usec = 0; int const iResult = select(0, 0, 0, 0, &tvDelay); // Again query the wall clock time. timeval tvEnd; gettimeofday(&tvEnd, 0); timeval tvElapsed; timersub(&tvEnd, &tvStart, &tvElapsed); double const dElapsed = tvElapsed.tv_sec + tvElapsed.tv_usec * 1e-6; printf("select() returned after %f s with result %d / errno = %d\n", dElapsed, iResult, errno); assert(iResult == 0); // At least one second must have elapsed during the select() call. assert(dElapsed >= 0.99); VERIFY(pthread_join(TID, 0) == 0); VERIFY(pthread_mutex_unlock(&s_Mutex) == 0); return 0; } /* Local variables: compile-command: "g++ -Wall -W ptk.cpp -o ptk -lpthread" End: */