11
11
*
12
12
*
13
13
* IDENTIFICATION
14
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.127 2009/06/23 18:13:23 mha Exp $
14
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.128 2009/07/24 17:58:31 tgl Exp $
15
15
*
16
16
* NOTES
17
17
*
@@ -118,44 +118,76 @@ static long win32_ssl_create_mutex = 0;
118
118
119
119
/*
120
120
* Macros to handle disabling and then restoring the state of SIGPIPE handling.
121
- * Note that DISABLE_SIGPIPE() must appear at the start of a block .
121
+ * On Windows, these are all no-ops since there's no SIGPIPEs .
122
122
*/
123
123
124
124
#ifndef WIN32
125
+
126
+ #define SIGPIPE_MASKED (conn ) ((conn)->sigpipe_so || (conn)->sigpipe_flag)
127
+
125
128
#ifdef ENABLE_THREAD_SAFETY
126
129
127
- #define DISABLE_SIGPIPE (failaction ) \
128
- sigset_t osigmask; \
129
- bool sigpipe_pending; \
130
- bool got_epipe = false; \
131
- \
132
- if (pq_block_sigpipe(&osigmask, &sigpipe_pending) < 0) \
133
- failaction
130
+ struct sigpipe_info
131
+ {
132
+ sigset_t oldsigmask ;
133
+ bool sigpipe_pending ;
134
+ bool got_epipe ;
135
+ };
134
136
135
- #define REMEMBER_EPIPE (cond ) \
137
+ #define DECLARE_SIGPIPE_INFO (spinfo ) struct sigpipe_info spinfo
138
+
139
+ #define DISABLE_SIGPIPE (conn , spinfo , failaction ) \
140
+ do { \
141
+ (spinfo).got_epipe = false; \
142
+ if (!SIGPIPE_MASKED(conn)) \
143
+ { \
144
+ if (pq_block_sigpipe(&(spinfo).oldsigmask, \
145
+ &(spinfo).sigpipe_pending) < 0) \
146
+ failaction; \
147
+ } \
148
+ } while (0)
149
+
150
+ #define REMEMBER_EPIPE (spinfo , cond ) \
136
151
do { \
137
152
if (cond) \
138
- got_epipe = true; \
153
+ (spinfo). got_epipe = true; \
139
154
} while (0)
140
155
141
- #define RESTORE_SIGPIPE () \
142
- pq_reset_sigpipe(&osigmask, sigpipe_pending, got_epipe)
143
- #else /* !ENABLE_THREAD_SAFETY */
156
+ #define RESTORE_SIGPIPE (conn , spinfo ) \
157
+ do { \
158
+ if (!SIGPIPE_MASKED(conn)) \
159
+ pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
160
+ (spinfo).got_epipe); \
161
+ } while (0)
144
162
145
- #define DISABLE_SIGPIPE (failaction ) \
146
- pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN)
163
+ #else /* !ENABLE_THREAD_SAFETY */
147
164
148
- #define REMEMBER_EPIPE ( cond )
165
+ #define DECLARE_SIGPIPE_INFO ( spinfo ) pqsigfunc spinfo = NULL
149
166
150
- #define RESTORE_SIGPIPE () \
151
- pqsignal(SIGPIPE, oldsighandler)
152
- #endif /* ENABLE_THREAD_SAFETY */
153
- #else /* WIN32 */
167
+ #define DISABLE_SIGPIPE (conn , spinfo , failaction ) \
168
+ do { \
169
+ if (!SIGPIPE_MASKED(conn)) \
170
+ spinfo = pqsignal(SIGPIPE, SIG_IGN); \
171
+ } while (0)
172
+
173
+ #define REMEMBER_EPIPE (spinfo , cond )
174
+
175
+ #define RESTORE_SIGPIPE (conn , spinfo ) \
176
+ do { \
177
+ if (!SIGPIPE_MASKED(conn)) \
178
+ pqsignal(SIGPIPE, spinfo); \
179
+ } while (0)
180
+
181
+ #endif /* ENABLE_THREAD_SAFETY */
154
182
155
- #define DISABLE_SIGPIPE (failaction )
156
- #define REMEMBER_EPIPE (cond )
157
- #define RESTORE_SIGPIPE ()
158
- #endif /* WIN32 */
183
+ #else /* WIN32 */
184
+
185
+ #define DECLARE_SIGPIPE_INFO (spinfo )
186
+ #define DISABLE_SIGPIPE (conn , spinfo , failaction )
187
+ #define REMEMBER_EPIPE (spinfo , cond )
188
+ #define RESTORE_SIGPIPE (conn , spinfo )
189
+
190
+ #endif /* WIN32 */
159
191
160
192
/* ------------------------------------------------------------ */
161
193
/* Procedures common to all secure sessions */
@@ -231,6 +263,9 @@ pqsecure_open_client(PGconn *conn)
231
263
/* First time through? */
232
264
if (conn -> ssl == NULL )
233
265
{
266
+ /* We cannot use MSG_NOSIGNAL to block SIGPIPE when using SSL */
267
+ conn -> sigpipe_flag = false;
268
+
234
269
if (!(conn -> ssl = SSL_new (SSL_context )) ||
235
270
!SSL_set_app_data (conn -> ssl , conn ) ||
236
271
!SSL_set_fd (conn -> ssl , conn -> sock ))
@@ -283,9 +318,10 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
283
318
if (conn -> ssl )
284
319
{
285
320
int err ;
321
+ DECLARE_SIGPIPE_INFO (spinfo );
286
322
287
323
/* SSL_read can write to the socket, so we need to disable SIGPIPE */
288
- DISABLE_SIGPIPE (return - 1 );
324
+ DISABLE_SIGPIPE (conn , spinfo , return - 1 );
289
325
290
326
rloop :
291
327
n = SSL_read (conn -> ssl , ptr , len );
@@ -312,7 +348,7 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
312
348
313
349
if (n == -1 )
314
350
{
315
- REMEMBER_EPIPE (SOCK_ERRNO == EPIPE );
351
+ REMEMBER_EPIPE (spinfo , SOCK_ERRNO == EPIPE );
316
352
printfPQExpBuffer (& conn -> errorMessage ,
317
353
libpq_gettext ("SSL SYSCALL error: %s\n" ),
318
354
SOCK_STRERROR (SOCK_ERRNO , sebuf , sizeof (sebuf )));
@@ -348,7 +384,7 @@ pqsecure_read(PGconn *conn, void *ptr, size_t len)
348
384
break ;
349
385
}
350
386
351
- RESTORE_SIGPIPE ();
387
+ RESTORE_SIGPIPE (conn , spinfo );
352
388
}
353
389
else
354
390
#endif
@@ -364,14 +400,15 @@ ssize_t
364
400
pqsecure_write (PGconn * conn , const void * ptr , size_t len )
365
401
{
366
402
ssize_t n ;
367
-
368
- DISABLE_SIGPIPE (return - 1 );
403
+ DECLARE_SIGPIPE_INFO (spinfo );
369
404
370
405
#ifdef USE_SSL
371
406
if (conn -> ssl )
372
407
{
373
408
int err ;
374
409
410
+ DISABLE_SIGPIPE (conn , spinfo , return - 1 );
411
+
375
412
n = SSL_write (conn -> ssl , ptr , len );
376
413
err = SSL_get_error (conn -> ssl , n );
377
414
switch (err )
@@ -396,7 +433,7 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
396
433
397
434
if (n == -1 )
398
435
{
399
- REMEMBER_EPIPE (SOCK_ERRNO == EPIPE );
436
+ REMEMBER_EPIPE (spinfo , SOCK_ERRNO == EPIPE );
400
437
printfPQExpBuffer (& conn -> errorMessage ,
401
438
libpq_gettext ("SSL SYSCALL error: %s\n" ),
402
439
SOCK_STRERROR (SOCK_ERRNO , sebuf , sizeof (sebuf )));
@@ -434,11 +471,41 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
434
471
else
435
472
#endif
436
473
{
437
- n = send (conn -> sock , ptr , len , 0 );
438
- REMEMBER_EPIPE (n < 0 && SOCK_ERRNO == EPIPE );
474
+ int flags = 0 ;
475
+
476
+ #ifdef MSG_NOSIGNAL
477
+ if (conn -> sigpipe_flag )
478
+ flags |= MSG_NOSIGNAL ;
479
+
480
+ retry_masked :
481
+
482
+ #endif /* MSG_NOSIGNAL */
483
+
484
+ DISABLE_SIGPIPE (conn , spinfo , return - 1 );
485
+
486
+ n = send (conn -> sock , ptr , len , flags );
487
+
488
+ if (n < 0 )
489
+ {
490
+ /*
491
+ * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't
492
+ * available on this machine. So, clear sigpipe_flag so we don't
493
+ * try the flag again, and retry the send().
494
+ */
495
+ #ifdef MSG_NOSIGNAL
496
+ if (flags != 0 && SOCK_ERRNO == EINVAL )
497
+ {
498
+ conn -> sigpipe_flag = false;
499
+ flags = 0 ;
500
+ goto retry_masked ;
501
+ }
502
+ #endif /* MSG_NOSIGNAL */
503
+
504
+ REMEMBER_EPIPE (spinfo , SOCK_ERRNO == EPIPE );
505
+ }
439
506
}
440
507
441
- RESTORE_SIGPIPE ();
508
+ RESTORE_SIGPIPE (conn , spinfo );
442
509
443
510
return n ;
444
511
}
@@ -1220,14 +1287,16 @@ close_SSL(PGconn *conn)
1220
1287
{
1221
1288
if (conn -> ssl )
1222
1289
{
1223
- DISABLE_SIGPIPE ((void ) 0 );
1290
+ DECLARE_SIGPIPE_INFO (spinfo );
1291
+
1292
+ DISABLE_SIGPIPE (conn , spinfo , (void ) 0 );
1224
1293
SSL_shutdown (conn -> ssl );
1225
1294
SSL_free (conn -> ssl );
1226
1295
conn -> ssl = NULL ;
1227
1296
pqsecure_destroy ();
1228
1297
/* We have to assume we got EPIPE */
1229
- REMEMBER_EPIPE (true);
1230
- RESTORE_SIGPIPE ();
1298
+ REMEMBER_EPIPE (spinfo , true);
1299
+ RESTORE_SIGPIPE (conn , spinfo );
1231
1300
}
1232
1301
1233
1302
if (conn -> peer )
0 commit comments