Re: SIGPIPE handling - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: SIGPIPE handling
Date
Msg-id 200311161621.hAGGLw521997@candle.pha.pa.us
Whole thread Raw
In response to SIGPIPE handling  (Manfred Spraul <manfred@colorfullife.com>)
Responses Re: SIGPIPE handling
Re: SIGPIPE handling
List pgsql-patches
Better.  However, I am confused over when we do sigaction.  I thought we
were going to do it only if they had a signal handler defined, meaning

    if (pipehandler != SIG_DFL &&
        pipehandler != SIG_IGN &&
        pipehandler != SIG_ERR)
        conn->do_sigaction = true;
    else
        conn->do_sigaction = false;

By doing this, we don't do sigaction in the default case where no
handler was defined.  I thought we would just set the entire application
to SIGPIPE <= SIG_IGN.  This gives us good performance in all cases
except when a signal handler is defined.  Is running the rest of the
application with SIGPIPE <= SIG_IGN a problem?

However, the code patch is:

    if (pipehandler == SIG_DFL || pipehandler == SIG_ERR)
        conn->do_sigaction = true;
    else
        conn->do_sigaction = false;

This gives us good performance only if SIGPIPE <= SIG_IGN has been set
by the application or a sigaction function has been defined.

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

Manfred Spraul wrote:
> Hi,
>
> attached is an update of my automatic sigaction patch: I've moved the
> actual sigaction calls into pqsignal.c and added a helper function
> (pgsignalinquire(signo)). I couldn't remove the include <signal.h> from
> fe-connect.c: it's required for the SIGPIPE definition.
> Additionally I've added a -a flag for pgbench that sets the signal
> handler before calling PQconnectdb.
>
> Tested on Fedora Core 1 (Redhat Linux) with pgbench.
>
> --
>     Manfred

> 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    16 Nov 2003 11:44:47 -0000
> ***************
> *** 41,46 ****
> --- 41,48 ----
>   #include <netinet/tcp.h>
>   #endif
>   #include <arpa/inet.h>
> + #include <signal.h>
> + #include "pqsignal.h"
>   #endif
>
>   #include "libpq/ip.h"
> ***************
> *** 881,886 ****
> --- 883,891 ----
>       struct addrinfo hint;
>       const char *node = NULL;
>       int            ret;
> + #ifndef WIN32
> +     pqsigfunc pipehandler;
> + #endif
>
>       if (!conn)
>           return 0;
> ***************
> *** 950,955 ****
> --- 955,976 ----
>           conn->allow_ssl_try = false;
>       else if (conn->sslmode[0] == 'a')    /* "allow" */
>           conn->wait_ssl_try = true;
> + #endif
> + #ifndef WIN32
> +     /*
> +      * 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.
> +      */
> +     pipehandler = pqsignalinquire(SIGPIPE);
> +     if (pipehandler == SIG_DFL || pipehandler == SIG_ERR)
> +         conn->do_sigaction = true;
> +     else
> +         conn->do_sigaction = false;
>   #endif
>
>       /*
> 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    16 Nov 2003 11:44:47 -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    16 Nov 2003 11:44:48 -0000
> ***************
> *** 329,334 ****
> --- 329,337 ----
>       char        peer_dn[256 + 1];        /* peer distinguished name */
>       char        peer_cn[SM_USER + 1];    /* peer common name */
>   #endif
> + #ifndef WIN32
> +     bool        do_sigaction;    /* set SIGPIPE to SIG_IGN around every send() call */
> + #endif
>
>       /* Buffer for current error message */
>       PQExpBufferData errorMessage;        /* expansible string */
> Index: src/interfaces/libpq/pqsignal.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/pqsignal.c,v
> retrieving revision 1.17
> diff -c -r1.17 pqsignal.c
> *** src/interfaces/libpq/pqsignal.c    4 Aug 2003 02:40:20 -0000    1.17
> --- src/interfaces/libpq/pqsignal.c    16 Nov 2003 11:44:48 -0000
> ***************
> *** 40,42 ****
> --- 40,61 ----
>       return oact.sa_handler;
>   #endif   /* !HAVE_POSIX_SIGNALS */
>   }
> +
> + pqsigfunc
> + pqsignalinquire(int signo)
> + {
> + #if !defined(HAVE_POSIX_SIGNALS)
> +     pqsigfunc old;
> +      old = signal(SIGPIPE, SIG_IGN);
> +     signal(SIGPIPE, old);
> +     return old;
> + #else
> +     struct sigaction oact;
> +
> +     if (sigaction(SIGPIPE, NULL, &oact) != 0)
> +            return SIG_ERR;
> +     return oact.sa_handler;
> + #endif   /* !HAVE_POSIX_SIGNALS */
> +
> +
> + }
> Index: src/interfaces/libpq/pqsignal.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/pqsignal.h,v
> retrieving revision 1.15
> diff -c -r1.15 pqsignal.h
> *** src/interfaces/libpq/pqsignal.h    4 Aug 2003 02:40:20 -0000    1.15
> --- src/interfaces/libpq/pqsignal.h    16 Nov 2003 11:44:48 -0000
> ***************
> *** 24,27 ****
> --- 24,29 ----
>
>   extern pqsigfunc pqsignal(int signo, pqsigfunc func);
>
> + extern pqsigfunc pqsignalinquire(int signo);
> +
>   #endif   /* PQSIGNAL_H */

> Index: contrib/pgbench/README.pgbench
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/contrib/pgbench/README.pgbench,v
> retrieving revision 1.9
> diff -c -r1.9 README.pgbench
> *** contrib/pgbench/README.pgbench    10 Jun 2003 09:07:15 -0000    1.9
> --- contrib/pgbench/README.pgbench    16 Nov 2003 11:44:39 -0000
> ***************
> *** 112,117 ****
> --- 112,121 ----
>           might be a security hole since ps command will
>           show the password. Use this for TESTING PURPOSE ONLY.
>
> +     -a
> +         Disable SIGPIPE delivery globally instead of within each
> +         libpq operation.
> +
>       -n
>           No vacuuming and cleaning the history table prior to the
>           test is performed.
> Index: contrib/pgbench/pgbench.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/contrib/pgbench/pgbench.c,v
> retrieving revision 1.27
> diff -c -r1.27 pgbench.c
> *** contrib/pgbench/pgbench.c    27 Sep 2003 19:15:34 -0000    1.27
> --- contrib/pgbench/pgbench.c    16 Nov 2003 11:44:39 -0000
> ***************
> *** 28,33 ****
> --- 28,34 ----
>   #else
>   #include <sys/time.h>
>   #include <unistd.h>
> + #include <signal.h>
>
>   #ifdef HAVE_GETOPT_H
>   #include <getopt.h>
> ***************
> *** 105,112 ****
>   static void
>   usage()
>   {
> !     fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s
scaling_factor][-n][-C][-v][-S][-N][-l][-Ulogin][-P password][-d][dbname]\n"); 
> !     fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor][-U login][-P
password][-d][dbname]\n");
>   }
>
>   /* random number generator */
> --- 106,113 ----
>   static void
>   usage()
>   {
> !     fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s
scaling_factor][-n][-C][-v][-S][-N][-l][-a][-Ulogin][-P password][-d][dbname]\n"); 
> !     fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor][-U login][-P
password][-d][dbname][-a]\n");
>   }
>
>   /* random number generator */
> ***************
> *** 703,712 ****
>       else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
>           login = env;
>
> !     while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNSl")) != -1)
>       {
>           switch (c)
>           {
>               case 'i':
>                   is_init_mode++;
>                   break;
> --- 704,718 ----
>       else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
>           login = env;
>
> !     while ((c = getopt(argc, argv, "aih:nvp:dc:t:s:U:P:CNSl")) != -1)
>       {
>           switch (c)
>           {
> +             case 'a':
> + #ifndef WIN32
> +                 signal(SIGPIPE, SIG_IGN);
> + #endif
> +                 break;
>               case 'i':
>                   is_init_mode++;
>                   break;

>
> ---------------------------(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: Hannu Krosing
Date:
Subject: Re: ALTER TABLE modifications
Next
From: Tom Lane
Date:
Subject: Re: SRA Win32 sync() code