Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Nov 1999 08:28:56 -0800
From:      "Scott Hess" <scott@avantgo.com>
To:        <freebsd-hackers@freebsd.org>
Subject:   EINTR problems with multithreaded programs.
Message-ID:  <030f01bf32ab$2d2c5620$1e80000a@avantgo.com>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

------=_NextPart_000_030C_01BF3268.1EFCBA10
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

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.

We're running MYSQL with a large number of connections (>1000), many of
which are idle at any given time (in a blocking read), and MYSQL uses alarm
signals in many places (it appears to be on a per-handled-query basis, but
I've not been able to pin this down quite yet).  The net result is that
with many idle connections and many active connections, the idle
connections get a _lot_ of EINTR.  By default, MYSQL takes 10 EINTR in a
row before dropping the connection - I've modified that upwards, but then
substantial amounts of CPU time are spent catching the EINTR and throwing
the thread back into the read (it's a relatively cheap operation - but
might happen a couple hundred thousand times a second).

I've tried using sigaction() in hopes of letting the system know that it
can restart the interrupted read(), but that doesn't seem to do the trick
in the attached program.  Any other options?

[Right now I'm seriously considering adding small sleeps to the EINTR case
in MYSQL.  At least then all the threads won't wake up on every signal.  I
know, I know, I should fix the use of signals, too, but that's going to
take a couple more weeks of becoming one with the code.]

Thanks,
scott


------=_NextPart_000_030C_01BF3268.1EFCBA10
Content-Type: application/octet-stream;
	name="thread_EINTR.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="thread_EINTR.c"

#include <pthread.h>=0A=
#include <errno.h>=0A=
#include <sys/types.h>=0A=
#include <signal.h>=0A=
=0A=
static void *reader( void *arg)=0A=
{=0A=
    char buf[ 1024];=0A=
    int cc;=0A=
    int fd=3D(int)arg;=0A=
    =0A=
    while(1) {=0A=
        printf( "%p waiting for data\n", pthread_self());=0A=
        cc=3Dread( fd, buf, sizeof( buf));=0A=
        if( cc>=3D0) {=0A=
            printf( "%p got %d bytes\n", pthread_self(), cc);=0A=
        } else {=0A=
            printf( "%p saw errno=3D=3D%d/%s\n", pthread_self(), errno, =
strerror( errno));=0A=
        }=0A=
    }=0A=
    return NULL;=0A=
}=0A=
=0A=
static void signal_handler( int sig)=0A=
{=0A=
    printf( "Got signal %d\n", sig);=0A=
}=0A=
=0A=
void main( void)=0A=
{=0A=
    int ii, cc=3D10;=0A=
    pthread_t child;=0A=
    =0A=
#if 0=0A=
    signal( SIGUSR1, signal_handler);=0A=
#else=0A=
    {=0A=
        struct sigaction sa=3D{ signal_handler, 0, SA_RESTART};=0A=
        sigaction( SIGUSR1, &sa, NULL);=0A=
    }=0A=
#endif=0A=
=0A=
    for( ii=3D0; ii<cc; ii++) {=0A=
        if( pthread_create( &child, NULL, reader, (void *)dup( 0))) {=0A=
            perror( "spawning thread");=0A=
            exit( 1);=0A=
        }=0A=
    }=0A=
    while( 1) {=0A=
        sleep( 2);=0A=
        kill( getpid(), SIGUSR1);=0A=
    }=0A=
    exit( 0);=0A=
}=0A=

------=_NextPart_000_030C_01BF3268.1EFCBA10--



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?030f01bf32ab$2d2c5620$1e80000a>