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: