Re: Avoiding SIGPIPE (was Re: OSDL DBT-2 w/ PostgreSQL - Mailing list pgsql-hackers
| From | Manfred Spraul |
|---|---|
| Subject | Re: Avoiding SIGPIPE (was Re: OSDL DBT-2 w/ PostgreSQL |
| Date | |
| Msg-id | 3FA6BF68.9060303@colorfullife.com Whole thread Raw |
| In response to | Re: Avoiding SIGPIPE (was Re: OSDL DBT-2 w/ PostgreSQL (Tom Lane <tgl@sss.pgh.pa.us>) |
| List | pgsql-hackers |
Tom Lane wrote:
>It strikes me that sigpipe handling will be a global affair in any
>particular application --- it's unlikely that it would be correct for
>some PG connections and wrong for others. So one possibility is to make
>the control variable be global (static) and thus it could be set before
>creating the first PGconn.
>
>
What about the attached patches?
I hope I found all places that must be updated when a new function is
added to libpq.
--
Manfred
Index: doc/src/sgml/libpq.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/libpq.sgml,v
retrieving revision 1.141
diff -c -r1.141 libpq.sgml
*** doc/src/sgml/libpq.sgml 1 Nov 2003 01:56:29 -0000 1.141
--- doc/src/sgml/libpq.sgml 3 Nov 2003 20:35:57 -0000
***************
*** 645,650 ****
--- 645,693 ----
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><function>PQsetsighandling</function><indexterm><primary>PQsetsighandling</></></term>
+ <term><function>PQgetsighandling</function><indexterm><primary>PQgetsighandling</></></term>
+ <listitem>
+ <para>
+ Set/query SIGPIPE signal handling.
+ <synopsis>
+ void PQsetsighandling(int internal_sigign);
+ </synopsis>
+ <synopsis>
+ int PQgetsighandling(void);
+ </synopsis>
+ </para>
+
+ <para>
+ These functions allow to query and set the SIGPIPE signal handling
+ of libpq: by default, Unix systems generate a (fatal) SIGPIPE signal
+ on a send to a socket that lost it's connection. Most callers expect
+ a normal error return instead of the signal. A normal error return
+ can be achieved by blocking or ignoring the SIGPIPE signal. This can
+ be done either globally in the application or inside libpq.
+ </para>
+ <para>
+ If internal signal handling is enabled (this is the default), then
+ libpq sets the SIGPIPE handler to SIG_IGN before every socket send
+ operation and restores it afterwards. This prevents libpq from
+ killing the application, at the cost of a slight performance
+ decrease. This approach is not reliable for multithreaded applications.
+ </para>
+ <para>
+ If internal signal handling is disabled, then the caller is
+ responsible for blocking or handling SIGPIPE signals. This is
+ recommended for multithreaded applications.
+ </para>
+ <para>
+ The signal handler setting is a global flag, it affects all
+ connections. The setting has no effect for Win32 clients - Win32
+ doesn't generate SIGPIPE events.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
</variablelist>
</para>
</sect1>
Index: src/interfaces/libpq/blibpqdll.def
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/blibpqdll.def,v
retrieving revision 1.9
diff -c -r1.9 blibpqdll.def
*** src/interfaces/libpq/blibpqdll.def 13 Aug 2003 16:29:03 -0000 1.9
--- src/interfaces/libpq/blibpqdll.def 3 Nov 2003 20:35:59 -0000
***************
*** 113,118 ****
--- 113,120 ----
_PQfformat @ 109
_PQexecPrepared @ 110
_PQsendQueryPrepared @ 111
+ _PQsetsighandling @ 112
+ _PQgetsighandling @ 113
; Aliases for MS compatible names
PQconnectdb = _PQconnectdb
***************
*** 226,228 ****
--- 228,232 ----
PQfformat = _PQfformat
PQexecPrepared = _PQexecPrepared
PQsendQueryPrepared = _PQsendQueryPrepared
+ PQsetsighandling = _PQsetsighandling
+ PQgetsighandling = _PQgetsighandling
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 3 Nov 2003 20:35:59 -0000
***************
*** 198,203 ****
--- 198,204 ----
-----END DH PARAMETERS-----\n";
#endif
+ static int do_sigaction = 1;
/* ------------------------------------------------------------ */
/* Procedures common to all secure sessions */
/* ------------------------------------------------------------ */
***************
*** 348,354 ****
ssize_t n;
#ifndef WIN32
! pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
#endif
#ifdef USE_SSL
--- 349,358 ----
ssize_t n;
#ifndef WIN32
! pqsigfunc oldsighandler = NULL;
!
! if (do_sigaction)
! oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
#endif
#ifdef USE_SSL
***************
*** 408,417 ****
n = send(conn->sock, ptr, len, 0);
#ifndef WIN32
! pqsignal(SIGPIPE, oldsighandler);
#endif
return n;
}
/* ------------------------------------------------------------ */
--- 412,432 ----
n = send(conn->sock, ptr, len, 0);
#ifndef WIN32
! if (do_sigaction)
! pqsignal(SIGPIPE, oldsighandler);
#endif
return n;
+ }
+
+ void PQsetsighandling(int internal_sigign)
+ {
+ do_sigaction = internal_sigign;
+ }
+
+ int PQgetsighandling(void)
+ {
+ return do_sigaction;
}
/* ------------------------------------------------------------ */
Index: src/interfaces/libpq/libpq-fe.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/libpq-fe.h,v
retrieving revision 1.100
diff -c -r1.100 libpq-fe.h
*** src/interfaces/libpq/libpq-fe.h 27 Aug 2003 00:33:34 -0000 1.100
--- src/interfaces/libpq/libpq-fe.h 3 Nov 2003 20:36:00 -0000
***************
*** 221,226 ****
--- 221,232 ----
/* free the data structure returned by PQconndefaults() */
extern void PQconninfoFree(PQconninfoOption *connOptions);
+ /* === in fe-secure.c === */
+
+ /* get/set SIGPIPE handling */
+ extern void PQsetsighandling(int internal_sigign);
+ extern int PQgetsighandling(void);
+
/*
* close the current connection and restablish a new one with the same
* parameters
? contrib/pgbench/pgbench
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 3 Nov 2003 19:53:13 -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 3 Nov 2003 19:53:15 -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,719 ----
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
+ PQsetsighandling(0);
+ break;
case 'i':
is_init_mode++;
break;
pgsql-hackers by date: