Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0150dbd

Browse files
committed
Allow libpq to do thread-safe SIGPIPE handling. This allows it to
ignore SIGPIPE from send() in libpq, but terminate on any other SIGPIPE,unless the user installs their own signal handler.This is a minor fix because the only time you get SIGPIPE from libpq'ssend() is when the backend dies.
1 parentacc5754 commit0150dbd

File tree

9 files changed

+167
-12
lines changed

9 files changed

+167
-12
lines changed

‎doc/src/sgml/libpq.sgml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.144 2003/12/13 23:59:06 neilc Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.145 2004/01/09 02:02:43 momjian Exp $
33
-->
44

55
<chapter id="libpq">
@@ -3587,7 +3587,7 @@ thread-enabled applications.
35873587
One restriction is that no two threads attempt to manipulate the same
35883588
<structname>PGconn</> object at the same time. In particular, you cannot
35893589
issue concurrent commands from different threads through the same
3590-
connection object. (If you need to run concurrent commands,start up
3590+
connection object. (If you need to run concurrent commands,use
35913591
multiple connections.)
35923592
</para>
35933593

@@ -3612,6 +3612,25 @@ not thread-safe.<indexterm><primary>crypt</><secondary>thread
36123612
safety</></> It is better to use the <literal>md5</literal> method,
36133613
which is thread-safe on all platforms.
36143614
</para>
3615+
3616+
<para>
3617+
<application>libpq</application> must ignore <literal>SIGPIPE</> signals
3618+
generated internally by <function>send()</> calls to backend processes.
3619+
When <productname>PostgreSQL</> is configured without
3620+
<literal>--enable-thread-safety</>, <application>libpq</> sets
3621+
<literal>SIGPIPE</> to <literal>SIG_IGN</> before each
3622+
<function>send()</> call and restores the original signal handler after
3623+
completion. When <literal>--enable-thread-safety</> is used,
3624+
<application>libpq</> installs its own <literal>SIGPIPE</> handler
3625+
before the first database connection if no custom <literal>SIGPIPE</>
3626+
handler has been installed previously. This handler uses thread-local
3627+
storage to determine if a <literal>SIGPIPE</> signal has been generated
3628+
by an internal <function>send()</>. If an application wants to install
3629+
its own <literal>SIGPIPE</> signal handler, it should call
3630+
<function>PQinSend()</> to determine if it should ignore the
3631+
<literal>SIGPIPE</> signal. This function is available in both
3632+
thread-safe and non-thread-safe versions of <application>libpq</>.
3633+
</para>
36153634
</sect1>
36163635

36173636

‎src/backend/nodes/read.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.37 2004/01/07 21:12:56 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/nodes/read.c,v 1.38 2004/01/09 02:02:43 momjian Exp $
1313
*
1414
* HISTORY
1515
* AUTHORDATEMAJOR EVENT
@@ -22,6 +22,7 @@
2222
#include<ctype.h>
2323
#include<errno.h>
2424

25+
#include"nodes/value.h"
2526
#include"nodes/pg_list.h"
2627
#include"nodes/readfuncs.h"
2728
#include"nodes/value.h"

‎src/interfaces/libpq/fe-connect.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.266 2004/01/07 18:56:29 neilc Exp $
11+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.267 2004/01/09 02:02:43 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -43,6 +43,10 @@
4343
#include<arpa/inet.h>
4444
#endif
4545

46+
#ifdefENABLE_THREAD_SAFETY
47+
#include<pthread.h>
48+
#endif
49+
4650
#include"libpq/ip.h"
4751
#include"mb/pg_wchar.h"
4852

@@ -66,7 +70,6 @@ longioctlsocket_ret=1;
6670
#defineDefaultSSLMode"disable"
6771
#endif
6872

69-
7073
/* ----------
7174
* Definition of the conninfo parameters and their fallback resources.
7275
*
@@ -198,6 +201,7 @@ static char *pwdfMatchesString(char *buf, char *token);
198201
staticchar*PasswordFromFile(char*hostname,char*port,char*dbname,
199202
char*username);
200203

204+
201205
/*
202206
*Connecting to a Database
203207
*
@@ -881,6 +885,12 @@ connectDBStart(PGconn *conn)
881885
structaddrinfohint;
882886
constchar*node=NULL;
883887
intret;
888+
#ifdefENABLE_THREAD_SAFETY
889+
staticpthread_once_tcheck_sigpipe_once=PTHREAD_ONCE_INIT;
890+
891+
/* Check only on first connection request */
892+
pthread_once(&check_sigpipe_once,check_sigpipe_handler);
893+
#endif
884894

885895
if (!conn)
886896
return0;
@@ -3158,3 +3168,4 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
31583168

31593169
#undef LINELEN
31603170
}
3171+

‎src/interfaces/libpq/fe-print.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* didn't really belong there.
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-print.c,v 1.49 2003/11/29 19:52:12 pgsql Exp $
13+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-print.c,v 1.50 2004/01/09 02:02:43 momjian Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -90,8 +90,10 @@ PQprint(FILE *fout,
9090
intfs_len=strlen(po->fieldSep);
9191
inttotal_line_length=0;
9292
intusePipe=0;
93-
pqsigfuncoldsigpipehandler=NULL;
9493
char*pagerenv;
94+
#if !defined(ENABLE_THREAD_SAFETY)&& !defined(WIN32)
95+
pqsigfuncoldsigpipehandler=NULL;
96+
#endif
9597

9698
#ifdefTIOCGWINSZ
9799
structwinsizescreen_size;
@@ -189,8 +191,12 @@ PQprint(FILE *fout,
189191
if (fout)
190192
{
191193
usePipe=1;
194+
#ifdefENABLE_THREAD_SAFETY
195+
pthread_setspecific(thread_in_send,"t");
196+
#else
192197
#ifndefWIN32
193198
oldsigpipehandler=pqsignal(SIGPIPE,SIG_IGN);
199+
#endif
194200
#endif
195201
}
196202
else
@@ -306,7 +312,13 @@ PQprint(FILE *fout,
306312
_pclose(fout);
307313
#else
308314
pclose(fout);
315+
#endif
316+
#ifdefENABLE_THREAD_SAFETY
317+
pthread_setspecific(thread_in_send,"f");
318+
#else
319+
#ifndefWIN32
309320
pqsignal(SIGPIPE,oldsigpipehandler);
321+
#endif
310322
#endif
311323
}
312324
if (po->html3&& !po->expanded)

‎src/interfaces/libpq/fe-secure.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.34 2003/12/18 22:49:26 tgl Exp $
14+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.35 2004/01/09 02:02:43 momjian Exp $
1515
*
1616
* NOTES
1717
* The client *requires* a valid server certificate. Since
@@ -106,6 +106,10 @@
106106
#include<arpa/inet.h>
107107
#endif
108108

109+
#ifdefENABLE_THREAD_SAFETY
110+
#include<pthread.h>
111+
#endif
112+
109113
#ifndefHAVE_STRDUP
110114
#include"strdup.h"
111115
#endif
@@ -142,6 +146,11 @@ static const char *SSLerrmessage(void);
142146
staticSSL_CTX*SSL_context=NULL;
143147
#endif
144148

149+
#ifdefENABLE_THREAD_SAFETY
150+
staticvoidsigpipe_handler_ignore_send(intsigno);
151+
pthread_key_tthread_in_send;
152+
#endif
153+
145154
/* ------------------------------------------------------------ */
146155
/* Hardcoded values*/
147156
/* ------------------------------------------------------------ */
@@ -347,9 +356,13 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
347356
{
348357
ssize_tn;
349358

359+
#ifdefENABLE_THREAD_SAFETY
360+
pthread_setspecific(thread_in_send,"t");
361+
#else
350362
#ifndefWIN32
351363
pqsigfuncoldsighandler=pqsignal(SIGPIPE,SIG_IGN);
352364
#endif
365+
#endif
353366

354367
#ifdefUSE_SSL
355368
if (conn->ssl)
@@ -407,8 +420,12 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
407420
#endif
408421
n=send(conn->sock,ptr,len,0);
409422

423+
#ifdefENABLE_THREAD_SAFETY
424+
pthread_setspecific(thread_in_send,"f");
425+
#else
410426
#ifndefWIN32
411427
pqsignal(SIGPIPE,oldsighandler);
428+
#endif
412429
#endif
413430

414431
returnn;
@@ -1048,3 +1065,59 @@ PQgetssl(PGconn *conn)
10481065
}
10491066

10501067
#endif/* USE_SSL */
1068+
1069+
1070+
#ifdefENABLE_THREAD_SAFETY
1071+
/*
1072+
*Check SIGPIPE handler and perhaps install our own.
1073+
*/
1074+
void
1075+
check_sigpipe_handler(void)
1076+
{
1077+
pqsigfuncpipehandler;
1078+
1079+
/*
1080+
*If the app hasn't set a SIGPIPE handler, define our own
1081+
*that ignores SIGPIPE on libpq send() and does SIG_DFL
1082+
*for other SIGPIPE cases.
1083+
*/
1084+
pipehandler=pqsignalinquire(SIGPIPE);
1085+
if (pipehandler==SIG_DFL)/* not set by application */
1086+
{
1087+
/*
1088+
*Create key first because the signal handler might be called
1089+
*right after being installed.
1090+
*/
1091+
pthread_key_create(&thread_in_send,NULL);
1092+
pqsignal(SIGPIPE,sigpipe_handler_ignore_send);
1093+
}
1094+
}
1095+
1096+
/*
1097+
*Threaded SIGPIPE signal handler
1098+
*/
1099+
void
1100+
sigpipe_handler_ignore_send(intsigno)
1101+
{
1102+
/* If we have gotten a SIGPIPE outside send(), exit */
1103+
if (!PQinSend())
1104+
exit(128+SIGPIPE);/* typical return value for SIG_DFL */
1105+
}
1106+
#endif
1107+
1108+
/*
1109+
*Indicates whether the current thread is in send()
1110+
*For use by SIGPIPE signal handlers; they should
1111+
*ignore SIGPIPE when libpq is in send(). This means
1112+
*that the backend has died unexpectedly.
1113+
*/
1114+
pqbool
1115+
PQinSend(void)
1116+
{
1117+
#ifdefENABLE_THREAD_SAFETY
1118+
return (pthread_getspecific(thread_in_send)/* has it been set? */&&
1119+
*(char*)pthread_getspecific(thread_in_send)=='t') ? true : false;
1120+
#else
1121+
return false;/* No threading, so we can't be in send() */
1122+
#endif
1123+
}

‎src/interfaces/libpq/libpq-fe.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.101 2003/11/29 22:41:28 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.102 2004/01/09 02:02:43 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -450,6 +450,14 @@ extern intPQmblen(const unsigned char *s, int encoding);
450450
/* Get encoding id from environment variable PGCLIENTENCODING */
451451
externintPQenv2encoding(void);
452452

453+
/* === in fe-secure.c === */
454+
455+
/*
456+
*Indicates whether the libpq thread is in send().
457+
*Used to ignore SIGPIPE if thread is in send().
458+
*/
459+
pqboolPQinSend(void);
460+
453461
#ifdef__cplusplus
454462
}
455463
#endif

‎src/interfaces/libpq/libpq-int.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
15-
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.83 2003/11/29 22:41:28 pgsql Exp $
15+
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.84 2004/01/09 02:02:43 momjian Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -29,6 +29,9 @@
2929
#include<sys/time.h>
3030
#endif
3131

32+
#ifdefENABLE_THREAD_SAFETY
33+
#include<pthread.h>
34+
#endif
3235

3336
#if defined(WIN32)&& (!defined(ssize_t))
3437
typedefintssize_t;/* ssize_t doesn't exist in VC (at least
@@ -442,6 +445,10 @@ extern PostgresPollingStatusType pqsecure_open_client(PGconn *);
442445
externvoidpqsecure_close(PGconn*);
443446
externssize_tpqsecure_read(PGconn*,void*ptr,size_tlen);
444447
externssize_tpqsecure_write(PGconn*,constvoid*ptr,size_tlen);
448+
#ifdefENABLE_THREAD_SAFETY
449+
externvoidcheck_sigpipe_handler(void);
450+
externpthread_key_tthread_in_send;
451+
#endif
445452

446453
/*
447454
* this is so that we can check if a connection is non-blocking internally

‎src/interfaces/libpq/pqsignal.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/interfaces/libpq/pqsignal.c,v 1.18 2003/11/29 19:52:12 pgsql Exp $
12+
* $PostgreSQL: pgsql/src/interfaces/libpq/pqsignal.c,v 1.19 2004/01/09 02:02:43 momjian Exp $
1313
*
1414
* NOTES
1515
*This shouldn't be in libpq, but the monitor and some other
@@ -40,3 +40,25 @@ pqsignal(int signo, pqsigfunc func)
4040
returnoact.sa_handler;
4141
#endif/* !HAVE_POSIX_SIGNALS */
4242
}
43+
44+
pqsigfunc
45+
pqsignalinquire(intsigno)
46+
{
47+
#if !defined(HAVE_POSIX_SIGNALS)
48+
pqsigfuncold_sigfunc;
49+
intold_sigmask;
50+
51+
/* Prevent signal handler calls during test */
52+
old_sigmask=sigblock(sigmask(signo));
53+
old_sigfunc=signal(signo,SIG_DFL);
54+
signal(signo,old_sigfunc);
55+
sigblock(old_sigmask);
56+
returnold_sigfunc;
57+
#else
58+
structsigactionoact;
59+
60+
if (sigaction(signo,NULL,&oact)<0)
61+
returnSIG_ERR;
62+
returnoact.sa_handler;
63+
#endif/* !HAVE_POSIX_SIGNALS */
64+
}

‎src/interfaces/libpq/pqsignal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/interfaces/libpq/pqsignal.h,v 1.16 2003/11/29 22:41:28 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/interfaces/libpq/pqsignal.h,v 1.17 2004/01/09 02:02:43 momjian Exp $
1111
*
1212
* NOTES
1313
* This shouldn't be in libpq, but the monitor and some other
@@ -24,4 +24,6 @@ typedef void (*pqsigfunc) (int);
2424

2525
externpqsigfuncpqsignal(intsigno,pqsigfuncfunc);
2626

27+
externpqsigfuncpqsignalinquire(intsigno);
28+
2729
#endif/* PQSIGNAL_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp