Mail Archives: cygwin/2010/07/12/17:06:10
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
FYI
Just to update some details.
I am working with James Cotton on the OpenPilot project.
We are trying to port the POSIX simulation port of FreeRTOS to cygwin.
We run into issues with signal handling in cygwin 1.7.5 that are
currently blocking our development, since every method to suspend a
running thread via signals either causes:
- random segfaults within Cygwin DLL.
or
- failure to execute the signal handler.
For the sake of narrowing down the source of our problems,
we created 8 demo test cases.
Each of them works the same way:
1. A thread is spawned via pthread_create(), which then executes some
code that is supposed to "sleep the thread" in background.
2. Signals are repeatedly sent to that thread using pthread_kill()
which are supposed to be handled by a signal handler.
3. Each succesful call to the signal handler writes a dot (.) to stderr
(using the write() system call to be thread safe)
Obviously what this is supposed to create is a neverending line of dots.
(Tested and working on Linux and Mac OS X on several architectures)
We believe this is a sign of a major flaw in cygwin signal handling and
may possibly affect many applications.
(Any application that uses signal handlers is potentially affected!)
SEGFAULTS usually occur only once in several thousand signals, so it is
a problem that won't appear on normal applications in a very frequent
way. However it is definitely reproducable!
All 8 test cases usually reach a stable state (segfault or freeze of
output) within less than 10 seconds (usually less than 1s) of run time.
The 8 test cases are as follows:
----
test_case_1_sleep.c
- The thread sleeps (literally) calling sleep() from <unistd.h>
Bug:
- After a couple thousand dots, the program ends with SIGSEGV in
cygwin1.dll. The backtrace leads to garbage due to stack corruption!
----
test_case_2_nanosleep.c
- The thread sleeps calling nanosleep() from <time.h>
Bug:
- After a couple thousand dots, the program ends with SIGSEGV in
cygwin1.dll. The backtrace leads to garbage due to stack corruption!
----
test_case_3_select.c
- The thread sleeps calling select() from <unistd.h>
Bug:
- Once select() is executed, cygwin blocks signals, failing to execute
the signal handler. No dots are printed (There is a violation to
POSIX specification. select() is supposed to return prematurely on
receiving any signal, whether handled or not. This does not happen.)
----
test_case_4_mutex_lock.c
- The thread sleeps calling pthread_mutex_lock() from <pthread.h>
Bug:
- Once mutex_lock() is executed, cygwin blocks signals, failing to
execute the signal handler. No dots are printed. This is a major
issue for the porting of FreeRTOS, because it causes deadlocks we
cannot resolve.
----
test_case_5_pselect.c
- The thread sleeps calling pselect() from <unistd.h>. Pselect allows
to specify a signal mask of signals to be (or not to be) blocked
during the pselect() call. The mask is deliberate set EMPTY to make
pselect() interrupt on ALL signals.
Bug:
- Once pselect() is executed, cygwin blocks signals, failing to execute
the signal handler. No dots are printed (pselect() completely
ignores its signal mask argument !!!!! )
----
test_case_6_sched_yield.c
- The thread "sleeps" repeatedly calling sched_yield() from <pthread.h>
Bug:
- The signal handler is not executed in a reliable fashion.
----
test_case_7_busy_waiting.c
- The thread runs like crazy in a busy loop.
Bug:
- The signal handler is not executed in a reliable fashion.
----
test_case_8_io.c
- The thread "sleeps" by executing a blocking "read()" call from stdin
Bug:
- The signal handler is not executed in a reliable fashion.
- Occasional segfaults in cygwin dll.
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_1_sleep.c
/**
* small test program whether signals between threads work as they should
*/
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
while (1) {
sleep(1);
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_2_nanosleep.c
/**
* small test program whether signals between threads work as they should
*/
#include <time.h>
#include <pthread.h>
#include <signal.h>
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
struct timespec sleeptime;
while (1) {
sleeptime.tv_sec=1;
sleeptime.tv_nsec=0;
nanosleep(&sleeptime,NULL);
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_3_select.c
/**
* small test program whether signals between threads work as they should
*/
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
struct timeval sleeptime;
while (1) {
sleeptime.tv_sec=1;
sleeptime.tv_usec=0;
select(0,NULL,NULL,NULL,&sleeptime);
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_4_mutex_lock.c
/**
* small etst program whether signals between threads work as they should
*/
#include <pthread.h>
#include <signal.h>
static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* actual test program
*/
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
while (1) {
pthread_mutex_lock(&Mutex);
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_mutex_lock(&Mutex);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_5_pselect.c
/**
* small test program whether signals between threads work as they should
*/
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
sigset_t sigset;
struct timespec sleeptime;
while (1) {
sleeptime.tv_sec=1;
sleeptime.tv_nsec=0;
sigemptyset(&sigset);
pselect(0,NULL,NULL,NULL,&sleeptime,&sigset);
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_6_sched_yield.c
/**
* small test program whether signals between threads work as they should
*/
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
while (1) {
sched_yield();
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_7_busy_waiting.c
/**
* small test program whether signals between threads work as they should
*/
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
while (1) {
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/x-c++src
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=test_case_8_io.c
/**
* small test program whether signals between threads work as they should
*/
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
void sighandler(int sig) {
write(2,".",1);
return;
}
void* threadstart(void* arg) {
char buf[1024];
while (1) {
read(1,buf,512);
}
}
int main(char** argc, int argv) {
pthread_t testthread1;
struct sigaction action;
action.sa_handler=sighandler;
action.sa_flags=0;
sigfillset( &action.sa_mask );
sigaction(SIGUSR1,&action,NULL);
pthread_create(&testthread1,NULL,threadstart,NULL);
while (1) {
pthread_kill(testthread1,SIGUSR1);
}
}
--MP_//2QRbacSOBFpiqJpH/m8fPe
Content-Type: text/plain; charset=us-ascii
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
--MP_//2QRbacSOBFpiqJpH/m8fPe--
- Raw text -