SIGPIPE handling - Mailing list pgsql-patches
From | Manfred Spraul |
---|---|
Subject | SIGPIPE handling |
Date | |
Msg-id | 3FB765DA.7020806@colorfullife.com Whole thread Raw |
Responses |
Re: SIGPIPE handling
Re: SIGPIPE handling |
List | pgsql-patches |
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;
pgsql-patches by date: