Hello, While porting a pthread-application from Linux to Cygwin I found out that pthread_kill() behaves differently on Linux and Cygwin. It looks like with Cygwin pthread_kill() sends a signal to the caller thread instead of the thread specified in the argument list. I have attached a test program and the output on Linux and on Cygwin with this E-mail (in the included output you can see that I ran the test program once on Cygwin, and four times on Linux).
Regards, Bart Van Assche.
#include <cassert> #include <cerrno> #include <cstring> #include <cstdio> #include <cstdlib> #include <pthread.h> #include <signal.h> #include <sys/time.h> #include <unistd.h> #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: */
select() returned after 0.999753 s with result 0 / errno = 0 select() returned after 0.999751 s with result 0 / errno = 0 select() returned after 0.999749 s with result 0 / errno = 0 select() returned after 1.000750 s with result 0 / errno = 0
select() returned after 0.000000 s with result -1 / errno = 4 assertion "iResult == 0" failed: file "ptk.cpp", line 76 Aborted (core dumped)
cygcheck.out
Description: Binary data
-- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/