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

Commit8408f65

Browse files
committed
Rework libpq threaded SIGPIPE handling to avoid interference with
calling applications. This is done by blocking sigpipe in the libpqthread and using sigpending/sigwait to possibily discard any sigpipe wegenerated.
1 parente02ef26 commit8408f65

File tree

9 files changed

+115
-107
lines changed

9 files changed

+115
-107
lines changed

‎configure

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17431,6 +17431,18 @@ _ACEOF
1743117431
fi
1743217432
HAVE_POSIX_SIGNALS=$pgac_cv_func_posix_signals
1743317433

17434+
if test "$pgac_cv_func_posix_signals" != yes -a "$enable_thread_safety" = yes; then
17435+
{ { echo "$as_me:$LINENO: error:
17436+
*** Thread-safety requires POSIX signals, which are not supported by your
17437+
*** operating system.
17438+
" >&5
17439+
echo "$as_me: error:
17440+
*** Thread-safety requires POSIX signals, which are not supported by your
17441+
*** operating system.
17442+
" >&2;}
17443+
{ (exit 1); exit 1; }; }
17444+
fi
17445+
1743417446
if test $ac_cv_func_fseeko = yes; then
1743517447
# Check whether --enable-largefile or --disable-largefile was given.
1743617448
if test "${enable_largefile+set}" = set; then

‎configure.in

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
dnl Process this file with autoconf to produce a configure script.
2-
dnl $PostgreSQL: pgsql/configure.in,v 1.387 2004/11/30 06:13:04 tgl Exp $
2+
dnl $PostgreSQL: pgsql/configure.in,v 1.388 2004/12/02 15:32:50 momjian Exp $
33
dnl
44
dnl Developers, please strive to achieve this order:
55
dnl
@@ -1174,6 +1174,13 @@ AC_CHECK_TYPES(sig_atomic_t, [], [], [#include <signal.h>])
11741174

11751175

11761176
PGAC_FUNC_POSIX_SIGNALS
1177+
if test "$pgac_cv_func_posix_signals" != yes -a "$enable_thread_safety" = yes; then
1178+
AC_MSG_ERROR([
1179+
*** Thread-safety requires POSIX signals, which are not supported by your
1180+
*** operating system.
1181+
])
1182+
fi
1183+
11771184
if test $ac_cv_func_fseeko = yes; then
11781185
AC_SYS_LARGEFILE
11791186
fi

‎doc/src/sgml/libpq.sgml

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.169 2004/11/27 21:56:04 petere Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.170 2004/12/02 15:32:52 momjian Exp $
33
-->
44

55
<chapter id="libpq">
@@ -3954,24 +3954,6 @@ safety</></> It is better to use the <literal>md5</literal> method,
39543954
which is thread-safe on all platforms.
39553955
</para>
39563956

3957-
<para>
3958-
<application>libpq</application> must ignore <literal>SIGPIPE</> signals
3959-
generated internally by <function>send()</> calls to backend processes.
3960-
When <productname>PostgreSQL</> is configured without
3961-
<literal>--enable-thread-safety</>, <application>libpq</> sets
3962-
<literal>SIGPIPE</> to <literal>SIG_IGN</> before each
3963-
<function>send()</> call and restores the original signal handler after
3964-
completion. When <literal>--enable-thread-safety</> is used,
3965-
<application>libpq</> installs its own <literal>SIGPIPE</> handler
3966-
before the first database connection. This handler uses thread-local
3967-
storage to determine if a <literal>SIGPIPE</> signal has been generated
3968-
by a libpq <function>send()</>. If an application wants to install
3969-
its own <literal>SIGPIPE</> signal handler, it should call
3970-
<function>PQinSend()</> to determine if it should ignore the
3971-
<literal>SIGPIPE</> signal. This function is available in both
3972-
thread-safe and non-thread-safe versions of <application>libpq</>.
3973-
</para>
3974-
39753957
<para>
39763958
If you experience problems with threaded applications, run
39773959
the program in <filename>src/tools/thread</> to see if your

‎doc/src/sgml/ref/copy.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.60 2004/11/27 21:56:05 petere Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/copy.sgml,v 1.61 2004/12/02 15:32:53 momjian Exp $
33
PostgreSQL documentation
44
-->
55

6+
67
<refentry id="SQL-COPY">
78
<refmeta>
89
<refentrytitle id="sql-copy-title">COPY</refentrytitle>

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

Lines changed: 1 addition & 10 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.290 2004/12/01 23:42:26 momjian Exp $
11+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.291 2004/12/02 15:32:54 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -866,15 +866,6 @@ connectDBStart(PGconn *conn)
866866
constchar*node=NULL;
867867
intret;
868868

869-
#ifdefENABLE_THREAD_SAFETY
870-
#ifndefWIN32
871-
staticpthread_once_tcheck_sigpipe_once=PTHREAD_ONCE_INIT;
872-
873-
/* Check only on first connection request */
874-
pthread_once(&check_sigpipe_once,pq_check_sigpipe_handler);
875-
#endif
876-
#endif
877-
878869
if (!conn)
879870
return0;
880871

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

Lines changed: 10 additions & 4 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.55 2004/11/09 15:57:57 petere Exp $
13+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-print.c,v 1.56 2004/12/02 15:32:54 momjian Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -91,7 +91,11 @@ PQprint(FILE *fout,
9191
inttotal_line_length=0;
9292
intusePipe=0;
9393
char*pagerenv;
94-
94+
#ifdefENABLE_THREAD_SAFETY
95+
sigset_tosigset;
96+
boolsigpipe_masked= false;
97+
boolsigpipe_pending;
98+
#endif
9599
#if !defined(ENABLE_THREAD_SAFETY)&& !defined(WIN32)
96100
pqsigfuncoldsigpipehandler=NULL;
97101
#endif
@@ -189,7 +193,8 @@ PQprint(FILE *fout,
189193
{
190194
usePipe=1;
191195
#ifdefENABLE_THREAD_SAFETY
192-
pthread_setspecific(pq_thread_in_send,"t");
196+
pq_block_sigpipe(&osigset,&sigpipe_pending);
197+
sigpipe_masked= true;
193198
#else
194199
#ifndefWIN32
195200
oldsigpipehandler=pqsignal(SIGPIPE,SIG_IGN);
@@ -311,7 +316,8 @@ PQprint(FILE *fout,
311316
pclose(fout);
312317
#endif
313318
#ifdefENABLE_THREAD_SAFETY
314-
pthread_setspecific(pq_thread_in_send,"f");
319+
if (sigpipe_masked)
320+
pq_reset_sigpipe(&osigset,sigpipe_pending);
315321
#else
316322
#ifndefWIN32
317323
pqsignal(SIGPIPE,oldsigpipehandler);

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

Lines changed: 73 additions & 59 deletions
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.57 2004/11/20 00:35:13 tgl Exp $
14+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.58 2004/12/02 15:32:54 momjian Exp $
1515
*
1616
* NOTES
1717
* [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -152,12 +152,6 @@ boolpq_initssllib = true;
152152
staticSSL_CTX*SSL_context=NULL;
153153
#endif
154154

155-
#ifdefENABLE_THREAD_SAFETY
156-
staticvoidsigpipe_handler_ignore_send(intsigno);
157-
pthread_key_tpq_thread_in_send=0;/* initializer needed on Darwin */
158-
staticpqsigfuncpq_pipe_handler;
159-
#endif
160-
161155
/* ------------------------------------------------------------ */
162156
/* Hardcoded values*/
163157
/* ------------------------------------------------------------ */
@@ -379,9 +373,12 @@ ssize_t
379373
pqsecure_write(PGconn*conn,constvoid*ptr,size_tlen)
380374
{
381375
ssize_tn;
382-
376+
383377
#ifdefENABLE_THREAD_SAFETY
384-
pthread_setspecific(pq_thread_in_send,"t");
378+
sigset_tosigmask;
379+
boolsigpipe_pending;
380+
381+
pq_block_sigpipe(&osigmask,&sigpipe_pending);
385382
#else
386383
#ifndefWIN32
387384
pqsigfuncoldsighandler=pqsignal(SIGPIPE,SIG_IGN);
@@ -452,9 +449,14 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
452449
else
453450
#endif
454451
n=send(conn->sock,ptr,len,0);
452+
/*
453+
*Possible optimization: if sigpending() turns out to be an
454+
*expensive operation, we can set sigpipe_pending = 'true'
455+
*here if errno != EPIPE, avoiding a sigpending call.
456+
*/
455457

456458
#ifdefENABLE_THREAD_SAFETY
457-
pthread_setspecific(pq_thread_in_send,"f");
459+
pq_reset_sigpipe(&osigmask,sigpipe_pending);
458460
#else
459461
#ifndefWIN32
460462
pqsignal(SIGPIPE,oldsighandler);
@@ -1216,65 +1218,77 @@ PQgetssl(PGconn *conn)
12161218
}
12171219
#endif/* USE_SSL */
12181220

1219-
12201221
#ifdefENABLE_THREAD_SAFETY
1221-
#ifndefWIN32
12221222
/*
1223-
*Check SIGPIPE handler and perhaps install our own.
1223+
*Block SIGPIPE for this thread. This prevents send()/write() from exiting
1224+
*the application.
12241225
*/
1225-
void
1226-
pq_check_sigpipe_handler(void)
1227-
{
1228-
pthread_key_create(&pq_thread_in_send,NULL);
1229-
1230-
/*
1231-
* Find current pipe handler and chain on to it.
1232-
*/
1233-
pq_pipe_handler=pqsignalinquire(SIGPIPE);
1234-
pqsignal(SIGPIPE,sigpipe_handler_ignore_send);
1235-
}
1236-
1237-
/*
1238-
*Threaded SIGPIPE signal handler
1239-
*/
1240-
void
1241-
sigpipe_handler_ignore_send(intsigno)
1226+
int
1227+
pq_block_sigpipe(sigset_t*osigset,bool*sigpipe_pending)
12421228
{
1243-
/*
1244-
* If we have gotten a SIGPIPE outside send(), chain or exit if we are
1245-
* at the end of the chain. Synchronous signals are delivered to the
1246-
* thread that caused the signal.
1247-
*/
1248-
if (!PQinSend())
1229+
sigset_tsigpipe_sigset;
1230+
sigset_tsigset;
1231+
intret;
1232+
1233+
sigemptyset(&sigpipe_sigset);
1234+
sigaddset(&sigpipe_sigset,SIGPIPE);
1235+
1236+
/* Block SIGPIPE and save previous mask for later reset */
1237+
ret=pthread_sigmask(SIG_BLOCK,&sigpipe_sigset,osigset);
1238+
1239+
/* We can have a pending SIGPIPE only if it was blocked before */
1240+
if (sigismember(osigset,SIGPIPE))
12491241
{
1250-
if (pq_pipe_handler==SIG_DFL)/* not set by application */
1251-
exit(128+SIGPIPE);/* typical return value for SIG_DFL */
1242+
/* Is there a pending SIGPIPE? */
1243+
if (sigpending(&sigset)!=0)
1244+
return-1;
1245+
1246+
if (sigismember(&sigset,SIGPIPE))
1247+
*sigpipe_pending= true;
12521248
else
1253-
(*pq_pipe_handler) (signo);/* call original handler */
1249+
*sigpipe_pending= false;
12541250
}
1251+
else
1252+
*sigpipe_pending= false;
1253+
1254+
returnret;
12551255
}
1256-
#endif
1257-
#endif
1258-
1256+
12591257
/*
1260-
*Indicates whether the current thread is in send()
1261-
*For use by SIGPIPE signal handlers; they should
1262-
*ignore SIGPIPE when libpq is in send(). This means
1263-
*that the backend has died unexpectedly.
1258+
*Discard any pending SIGPIPE and reset the signal mask.
1259+
*We might be discarding a blocked SIGPIPE that we didn't generate,
1260+
*but we document that you can't keep blocked SIGPIPE calls across
1261+
*libpq function calls.
12641262
*/
1265-
pqbool
1266-
PQinSend(void)
1263+
int
1264+
pq_reset_sigpipe(sigset_t*osigset,boolsigpipe_pending)
12671265
{
1268-
#ifdefENABLE_THREAD_SAFETY
1269-
return (pthread_getspecific(pq_thread_in_send)/* has it been set? */&&
1270-
*(char*)pthread_getspecific(pq_thread_in_send)=='t') ? true : false;
1271-
#else
1266+
intsigno;
1267+
sigset_tsigset;
12721268

1273-
/*
1274-
* No threading: our code ignores SIGPIPE around send(). Therefore, we
1275-
* can't be in send() if we are checking from a SIGPIPE signal
1276-
* handler.
1277-
*/
1278-
return false;
1279-
#endif
1269+
/* Clear SIGPIPE only if none was pending */
1270+
if (!sigpipe_pending)
1271+
{
1272+
if (sigpending(&sigset)!=0)
1273+
return-1;
1274+
1275+
/*
1276+
*Discard pending and blocked SIGPIPE
1277+
*/
1278+
if (sigismember(&sigset,SIGPIPE))
1279+
{
1280+
sigset_tsigpipe_sigset;
1281+
1282+
sigemptyset(&sigpipe_sigset);
1283+
sigaddset(&sigpipe_sigset,SIGPIPE);
1284+
1285+
sigwait(&sigpipe_sigset,&signo);
1286+
if (signo!=SIGPIPE)
1287+
return-1;
1288+
}
1289+
}
1290+
1291+
/* Restore saved block mask */
1292+
returnpthread_sigmask(SIG_SETMASK,osigset,NULL);
12801293
}
1294+
#endif

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2004, 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.113 2004/10/30 23:11:27 tgl Exp $
10+
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.114 2004/12/02 15:32:54 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -497,12 +497,6 @@ extern intPQenv2encoding(void);
497497

498498
/* === in fe-secure.c === */
499499

500-
/*
501-
*Indicates whether the libpq thread is in send().
502-
*Used to ignore SIGPIPE if thread is in send().
503-
*/
504-
externpqboolPQinSend(void);
505-
506500
#ifdef__cplusplus
507501
}
508502
#endif

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Portions Copyright (c) 1996-2004, 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.96 2004/10/30 23:11:27 tgl Exp $
15+
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.97 2004/12/02 15:32:54 momjian Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -31,6 +31,7 @@
3131

3232
#ifdefENABLE_THREAD_SAFETY
3333
#include<pthread.h>
34+
#include<signal.h>
3435
#endif
3536

3637
#ifdefWIN32_CLIENT_ONLY
@@ -475,15 +476,15 @@ extern void pqsecure_close(PGconn *);
475476
externssize_tpqsecure_read(PGconn*,void*ptr,size_tlen);
476477
externssize_tpqsecure_write(PGconn*,constvoid*ptr,size_tlen);
477478

478-
#ifdefENABLE_THREAD_SAFETY
479-
externvoidpq_check_sigpipe_handler(void);
480-
externpthread_key_tpq_thread_in_send;
481-
#endif
482-
483479
#ifdefUSE_SSL
484480
externboolpq_initssllib;
485481
#endif
486482

483+
#ifdefENABLE_THREAD_SAFETY
484+
intpq_block_sigpipe(sigset_t*osigset,bool*sigpipe_pending);
485+
intpq_reset_sigpipe(sigset_t*osigset,boolsigpipe_pending);
486+
#endif
487+
487488
/*
488489
* this is so that we can check if a connection is non-blocking internally
489490
* without the overhead of a function call

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp