Re: SIGPIPE handling, take two. - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: SIGPIPE handling, take two.
Date
Msg-id 200311110540.hAB5ehP28299@candle.pha.pa.us
Whole thread Raw
In response to SIGPIPE handling, take two.  (Manfred Spraul <manfred@colorfullife.com>)
Responses Re: SIGPIPE handling, take two.  (Gaetano Mendola <mendola@bigfoot.com>)
Re: SIGPIPE handling, take two.  (Tom Lane <tgl@sss.pgh.pa.us>)
Re: SIGPIPE handling, take two.  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
I think this is the patch I like.  It does the auto-detect handling as I
hoped.  I will just do the doc updates to mention it.

My only issue is that this is per-connection, while I think you have to
create a global variable that defaults to false, and on first connect,
check, and not after.  Based on the code below, a second connection
would  have the SIGPIPE signal set to SIG_IGN, not SIG_DEF, and you
would be back to setting SIG_IGN around each send, even though it was
already set.

Are others OK with this too?

---------------------------------------------------------------------------

Manfred Spraul wrote:
> pqsecure_write tries to catch SIGPIPE signals generated by network
> disconnects by setting the signal handler to SIG_IGN. The current
> approach causes several problems:
> - it always sets SA_RESTART when it restores the old handler.
> - it's not reliable for multi threaded apps, because another thread
> could change the signal handler inbetween.
> - it's slow, because after setting a signal handler to SIG_IGN the
> kernel must enumerate all threads and clear all pending signals (at
> least FreeBSD-5.1 and linux-2.6 do that. Earlier linux kernels don't -
> their signal handling is known to be broken for multithreaded apps).
>
> Initially I proposed a new option for PQconnectdb, but Tom didn't like
> that. The attached patch autodetects if it should set the signal
> handler, Tom proposed that. The code doesn't try to check if the signal
> is "handled" by blocking it, because I haven't figured out how to check
> that: sigprocmask is undefined for multithreaded apps and calling
> pthread_sigmask would force every libpq user to link against libpthread.
>
> --
>     Manfred

> ? src/interfaces/libpq/libpq.so.3.1
> Index: src/interfaces/libpq/fe-connect.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
> retrieving revision 1.263
> diff -c -r1.263 fe-connect.c
> *** src/interfaces/libpq/fe-connect.c    18 Oct 2003 05:02:06 -0000    1.263
> --- src/interfaces/libpq/fe-connect.c    2 Nov 2003 18:29:40 -0000
> ***************
> *** 41,46 ****
> --- 41,47 ----
>   #include <netinet/tcp.h>
>   #endif
>   #include <arpa/inet.h>
> + #include <signal.h>
>   #endif
>
>   #include "libpq/ip.h"
> ***************
> *** 951,956 ****
> --- 952,983 ----
>       else if (conn->sslmode[0] == 'a')    /* "allow" */
>           conn->wait_ssl_try = true;
>   #endif
> +     /*
> +      * Autodetect SIGPIPE signal handling:
> +      * The default action per Unix spec is kill current process and
> +      * that's not acceptable. If the current setting is not the default,
> +      * then assume that the caller knows what he's doing and leave the
> +      * signal handler unchanged. Otherwise set the signal handler to
> +      * SIG_IGN around each send() syscall. Unfortunately this is both
> +      * unreliable and slow for multithreaded apps.
> +      */
> +     conn->do_sigaction = true;
> + #if !defined(HAVE_POSIX_SIGNALS)
> +     {
> +         pqsigfunc old;
> +          old = signal(SIGPIPE, SIG_IGN);
> +         if (old != SIG_DFL)
> +             conn->do_sigaction = false;
> +         signal(SIGPIPE, old);
> +     }
> + #else
> +     {
> +         struct sigaction oact;
> +
> +         if (sigaction(SIGPIPE, NULL, &oact) == 0 && oact.sa_handler != SIG_DFL)
> +             conn->do_sigaction = false;
> +     }
> + #endif   /* !HAVE_POSIX_SIGNALS */
>
>       /*
>        * Set up to try to connect, with protocol 3.0 as the first attempt.
> Index: src/interfaces/libpq/fe-secure.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-secure.c,v
> retrieving revision 1.32
> diff -c -r1.32 fe-secure.c
> *** src/interfaces/libpq/fe-secure.c    29 Sep 2003 16:38:04 -0000    1.32
> --- src/interfaces/libpq/fe-secure.c    2 Nov 2003 18:29:41 -0000
> ***************
> *** 348,354 ****
>       ssize_t        n;
>
>   #ifndef WIN32
> !     pqsigfunc    oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
>   #endif
>
>   #ifdef USE_SSL
> --- 348,357 ----
>       ssize_t        n;
>
>   #ifndef WIN32
> !     pqsigfunc    oldsighandler = NULL;
> !
> !     if (conn->do_sigaction)
> !         oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
>   #endif
>
>   #ifdef USE_SSL
> ***************
> *** 408,414 ****
>           n = send(conn->sock, ptr, len, 0);
>
>   #ifndef WIN32
> !     pqsignal(SIGPIPE, oldsighandler);
>   #endif
>
>       return n;
> --- 411,418 ----
>           n = send(conn->sock, ptr, len, 0);
>
>   #ifndef WIN32
> !     if (conn->do_sigaction)
> !         pqsignal(SIGPIPE, oldsighandler);
>   #endif
>
>       return n;
> Index: src/interfaces/libpq/libpq-int.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-int.h,v
> retrieving revision 1.82
> diff -c -r1.82 libpq-int.h
> *** src/interfaces/libpq/libpq-int.h    5 Sep 2003 02:08:36 -0000    1.82
> --- src/interfaces/libpq/libpq-int.h    2 Nov 2003 18:29:42 -0000
> ***************
> *** 329,334 ****
> --- 329,335 ----
>       char        peer_dn[256 + 1];        /* peer distinguished name */
>       char        peer_cn[SM_USER + 1];    /* peer common name */
>   #endif
> +     bool        do_sigaction;    /* set SIGPIPE to SIG_IGN around every send() call */
>
>       /* Buffer for current error message */
>       PQExpBufferData errorMessage;        /* expansible string */

>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: sigpipe handling
Next
From: Gaetano Mendola
Date:
Subject: Re: SIGPIPE handling, take two.