From owner-freebsd-hackers Fri Nov 19 8:30: 0 1999 Delivered-To: freebsd-hackers@freebsd.org Received: from bomber.avantgo.com (ws1.avantgo.com [207.214.200.194]) by hub.freebsd.org (Postfix) with ESMTP id 0BD1215666 for ; Fri, 19 Nov 1999 08:29:57 -0800 (PST) (envelope-from scott@avantgo.com) Received: from river ([10.0.128.30]) by bomber.avantgo.com (Netscape Messaging Server 3.5) with SMTP id 377 for ; Fri, 19 Nov 1999 08:25:47 -0800 Message-ID: <030f01bf32ab$2d2c5620$1e80000a@avantgo.com> From: "Scott Hess" To: Subject: EINTR problems with multithreaded programs. Date: Fri, 19 Nov 1999 08:28:56 -0800 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_030C_01BF3268.1EFCBA10" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.00.2314.1300 X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300 Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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 =0A= #include =0A= #include =0A= #include =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