1111 *
1212 *
1313 * IDENTIFICATION
14- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.101 2008/01/01 19:46:00 momjian Exp $
14+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.102 2008/01/29 02:03:39 tgl Exp $
1515 *
1616 * NOTES
1717 * [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -162,6 +162,50 @@ static bool pq_initssllib = true;
162162static SSL_CTX * SSL_context = NULL ;
163163#endif
164164
165+ /*
166+ * Macros to handle disabling and then restoring the state of SIGPIPE handling.
167+ * Note that DISABLE_SIGPIPE() must appear at the start of a block.
168+ */
169+
170+ #ifndef WIN32
171+ #ifdef ENABLE_THREAD_SAFETY
172+
173+ #define DISABLE_SIGPIPE (failaction ) \
174+ sigset_t osigmask; \
175+ bool sigpipe_pending; \
176+ bool got_epipe = false; \
177+ \
178+ if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0) \
179+ failaction
180+
181+ #define REMEMBER_EPIPE (cond ) \
182+ do { \
183+ if (cond) \
184+ got_epipe = true; \
185+ } while (0)
186+
187+ #define RESTORE_SIGPIPE () \
188+ pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe)
189+
190+ #else /* !ENABLE_THREAD_SAFETY */
191+
192+ #define DISABLE_SIGPIPE (failaction ) \
193+ pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN)
194+
195+ #define REMEMBER_EPIPE (cond )
196+
197+ #define RESTORE_SIGPIPE () \
198+ pqsignal(SIGPIPE, oldsighandler)
199+
200+ #endif /* ENABLE_THREAD_SAFETY */
201+ #else /* WIN32 */
202+
203+ #define DISABLE_SIGPIPE (failaction )
204+ #define REMEMBER_EPIPE (cond )
205+ #define RESTORE_SIGPIPE ()
206+
207+ #endif /* WIN32 */
208+
165209/* ------------------------------------------------------------ */
166210/* Procedures common to all secure sessions */
167211/* ------------------------------------------------------------ */
@@ -268,6 +312,9 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
268312 {
269313 int err ;
270314
315+ /* SSL_read can write to the socket, so we need to disable SIGPIPE */
316+ DISABLE_SIGPIPE (return - 1 );
317+
271318rloop :
272319 n = SSL_read (conn -> ssl , ptr , len );
273320 err = SSL_get_error (conn -> ssl , n );
@@ -292,9 +339,12 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
292339 char sebuf [256 ];
293340
294341 if (n == -1 )
342+ {
343+ REMEMBER_EPIPE (SOCK_ERRNO == EPIPE );
295344 printfPQExpBuffer (& conn -> errorMessage ,
296345 libpq_gettext ("SSL SYSCALL error: %s\n" ),
297346 SOCK_STRERROR (SOCK_ERRNO , sebuf , sizeof (sebuf )));
347+ }
298348 else
299349 {
300350 printfPQExpBuffer (& conn -> errorMessage ,
@@ -325,6 +375,8 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
325375 n = -1 ;
326376 break ;
327377 }
378+
379+ RESTORE_SIGPIPE ();
328380 }
329381 else
330382#endif
@@ -341,19 +393,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
341393{
342394 ssize_t n ;
343395
344- #ifndef WIN32
345- #ifdef ENABLE_THREAD_SAFETY
346- sigset_t osigmask ;
347- bool sigpipe_pending ;
348- bool got_epipe = false;
349-
350-
351- if (pq_block_sigpipe (& osigmask , & sigpipe_pending ) < 0 )
352- return -1 ;
353- #else
354- pqsigfunc oldsighandler = pqsignal (SIGPIPE , SIG_IGN );
355- #endif /* ENABLE_THREAD_SAFETY */
356- #endif /* WIN32 */
396+ DISABLE_SIGPIPE (return - 1 );
357397
358398#ifdef USE_SSL
359399 if (conn -> ssl )
@@ -384,10 +424,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
384424
385425 if (n == -1 )
386426 {
387- #if defined(ENABLE_THREAD_SAFETY ) && !defined(WIN32 )
388- if (SOCK_ERRNO == EPIPE )
389- got_epipe = true;
390- #endif
427+ REMEMBER_EPIPE (SOCK_ERRNO == EPIPE );
391428 printfPQExpBuffer (& conn -> errorMessage ,
392429 libpq_gettext ("SSL SYSCALL error: %s\n" ),
393430 SOCK_STRERROR (SOCK_ERRNO , sebuf , sizeof (sebuf )));
@@ -426,19 +463,10 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
426463#endif
427464 {
428465 n = send (conn -> sock , ptr , len , 0 );
429- #if defined(ENABLE_THREAD_SAFETY ) && !defined(WIN32 )
430- if (n < 0 && SOCK_ERRNO == EPIPE )
431- got_epipe = true;
432- #endif
466+ REMEMBER_EPIPE (n < 0 && SOCK_ERRNO == EPIPE );
433467 }
434468
435- #ifndef WIN32
436- #ifdef ENABLE_THREAD_SAFETY
437- pq_reset_sigpipe (& osigmask , sigpipe_pending , got_epipe );
438- #else
439- pqsignal (SIGPIPE , oldsighandler );
440- #endif /* ENABLE_THREAD_SAFETY */
441- #endif /* WIN32 */
469+ RESTORE_SIGPIPE ();
442470
443471 return n ;
444472}
@@ -1092,9 +1120,13 @@ close_SSL(PGconn *conn)
10921120{
10931121 if (conn -> ssl )
10941122 {
1123+ DISABLE_SIGPIPE ((void ) 0 );
10951124 SSL_shutdown (conn -> ssl );
10961125 SSL_free (conn -> ssl );
10971126 conn -> ssl = NULL ;
1127+ /* We have to assume we got EPIPE */
1128+ REMEMBER_EPIPE (true);
1129+ RESTORE_SIGPIPE ();
10981130 }
10991131
11001132 if (conn -> peer )
@@ -1167,6 +1199,7 @@ PQgetssl(PGconn *conn)
11671199}
11681200#endif /* USE_SSL */
11691201
1202+
11701203#if defined(ENABLE_THREAD_SAFETY ) && !defined(WIN32 )
11711204
11721205/*
@@ -1251,4 +1284,4 @@ pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
12511284 SOCK_ERRNO_SET (save_errno );
12521285}
12531286
1254- #endif /* ENABLE_THREAD_SAFETY */
1287+ #endif /* ENABLE_THREAD_SAFETY && !WIN32 */
0 commit comments