sigpipe handling - Mailing list pgsql-patches
From | Manfred Spraul |
---|---|
Subject | sigpipe handling |
Date | |
Msg-id | 3FAD69CF.1070604@colorfullife.com Whole thread Raw |
Responses |
Re: sigpipe handling
|
List | pgsql-patches |
Attatched is the latest version of my patch that makes the signal(SIG_PIPE, SIG_IGN) calls around the send() syscall conditional: they are not sufficient to ensure that multithreaded libpq users are not killed by SIGPIPE signals, and they cause a noticable slowdown. I've switched to a global flag, and two functions to get/set the flag. Any other ideas how to protect libpq against SIGPIPE? -- Manfred 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 8 Nov 2003 21:43:53 -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 8 Nov 2003 21:43:54 -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; 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 8 Nov 2003 21:43:56 -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 write attempts to a disconnected socket. 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 8 Nov 2003 21:43:57 -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 8 Nov 2003 21:43:58 -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 8 Nov 2003 21:43:58 -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
pgsql-patches by date: