Date: Fri, 19 Nov 1999 10:18:22 -0800 From: "Scott Hess" <scott@avantgo.com> To: "Daniel Eischen" <eischen@vigrid.com>, <freebsd-hackers@FreeBSD.ORG> Subject: Re: EINTR problems with multithreaded programs. Message-ID: <03e501bf32ba$76d83550$1e80000a@avantgo.com> References: <199911191814.NAA02164@pcnet1.pcnet.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Daniel Eischen <eischen@vigrid.com> wrote:
>Scott Hess mailto:scott@avantgo.com wrote:
> > When using -pthread on FreeBSD3.3 to build a multithreaded program, I
find
> > that signals are delivered to all threads (see attached program).
> > Specifically, if multiple threads are in blocking read calls, and a
signal
> > is handled, they will all receive -1 from the read and EINTR in errno.
>
> If you don't want all threads to see the signal(s), then you
> have to block the signal(s) in each thread.
I've checked further, and found that FreeBSD correctly handles blocking
signals on a per-thread basis. _But_, all threads still get EINTR when a
signal happens while they're in a blocking read.
I've attached the updated program that shows the correct delivery of the
signals, with system calls still being interrupted. [Sorry about the
attachment, but that seems the safest way to go about getting the file
delivered in usable fashion.]
Thanks,
scott
[-- Attachment #2 --]
#include <pthread.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
static void signal_handler( int sig)
{
printf( "%p Got signal %d\n", pthread_self(), sig);
}
static void *reader( void *arg)
{
char buf[ 1024];
int cc;
int ii=(int)arg;
int fd=dup( 0);
sigset_t set;
sigemptyset( &set);
if( (ii%3)==0 || (ii%3)==1) {
sigaddset( &set, SIGUSR1);
}
if( (ii%3)==0 || (ii%3)==2) {
sigaddset( &set, SIGUSR2);
}
pthread_sigmask( SIG_BLOCK, &set, NULL);
{
struct sigaction sa_usr1={ signal_handler, 0, SA_RESTART};
struct sigaction sa_usr2={ signal_handler, 0, SA_RESTART};
sigaction( SIGUSR1, &sa_usr1, NULL);
sigaction( SIGUSR2, &sa_usr2, NULL);
}
printf( "%p/%d waiting for data\n", pthread_self(), ii);
while(1) {
cc=read( fd, buf, sizeof( buf));
if( cc>=0) {
printf( "%p got %d bytes\n", pthread_self(), cc);
} else {
printf( "%p saw errno==%d/%s\n", pthread_self(), errno, strerror( errno));
}
}
return NULL;
}
void main( void)
{
int ii, cc=9;
pthread_t child;
#if 0
signal( SIGUSR1, signal_handler);
#else
{
struct sigaction sa_usr1={ signal_handler, 0, SA_RESTART};
struct sigaction sa_usr2={ signal_handler, 0, SA_RESTART};
sigaction( SIGUSR1, &sa_usr1, NULL);
sigaction( SIGUSR2, &sa_usr2, NULL);
}
#endif
for( ii=0; ii<cc; ii++) {
if( pthread_create( &child, NULL, reader, (void *)ii)) {
perror( "spawning thread");
exit( 1);
}
}
while( 1) {
sleep( 2);
kill( getpid(), SIGUSR1);
sleep( 2);
kill( getpid(), SIGUSR2);
}
exit( 0);
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?03e501bf32ba$76d83550$1e80000a>
