11
11
*
12
12
*
13
13
* IDENTIFICATION
14
- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.58 2004/12/02 15:32:54 momjian Exp $
14
+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.59 2004/12/02 23:20:21 tgl Exp $
15
15
*
16
16
* NOTES
17
17
* [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -147,7 +147,7 @@ static void SSLerrfree(char *buf);
147
147
#endif
148
148
149
149
#ifdef USE_SSL
150
- bool pq_initssllib = true;
150
+ static bool pq_initssllib = true;
151
151
152
152
static SSL_CTX * SSL_context = NULL ;
153
153
#endif
@@ -212,6 +212,19 @@ KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
212
212
/* Procedures common to all secure sessions */
213
213
/* ------------------------------------------------------------ */
214
214
215
+
216
+ /*
217
+ * Exported (but as yet undocumented) function to allow application to
218
+ * tell us it's already initialized OpenSSL.
219
+ */
220
+ void
221
+ PQinitSSL (int do_init )
222
+ {
223
+ #ifdef USE_SSL
224
+ pq_initssllib = do_init ;
225
+ #endif
226
+ }
227
+
215
228
/*
216
229
* Initialize global context
217
230
*/
@@ -377,8 +390,10 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
377
390
#ifdef ENABLE_THREAD_SAFETY
378
391
sigset_t osigmask ;
379
392
bool sigpipe_pending ;
393
+ bool got_epipe = false;
380
394
381
- pq_block_sigpipe (& osigmask , & sigpipe_pending );
395
+ if (pq_block_sigpipe (& osigmask , & sigpipe_pending ) < 0 )
396
+ return -1 ;
382
397
#else
383
398
#ifndef WIN32
384
399
pqsigfunc oldsighandler = pqsignal (SIGPIPE , SIG_IGN );
@@ -413,9 +428,13 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
413
428
char sebuf [256 ];
414
429
415
430
if (n == -1 )
431
+ {
432
+ if (SOCK_ERRNO == EPIPE )
433
+ got_epipe = true;
416
434
printfPQExpBuffer (& conn -> errorMessage ,
417
435
libpq_gettext ("SSL SYSCALL error: %s\n" ),
418
436
SOCK_STRERROR (SOCK_ERRNO , sebuf , sizeof (sebuf )));
437
+ }
419
438
else
420
439
{
421
440
printfPQExpBuffer (& conn -> errorMessage ,
@@ -448,15 +467,16 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
448
467
}
449
468
else
450
469
#endif
470
+ {
451
471
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
- */
472
+ #ifdef ENABLE_THREAD_SAFETY
473
+ if ( n < 0 && SOCK_ERRNO == EPIPE )
474
+ got_epipe = true;
475
+ #endif
476
+ }
457
477
458
478
#ifdef ENABLE_THREAD_SAFETY
459
- pq_reset_sigpipe (& osigmask , sigpipe_pending );
479
+ pq_reset_sigpipe (& osigmask , sigpipe_pending , got_epipe );
460
480
#else
461
481
#ifndef WIN32
462
482
pqsignal (SIGPIPE , oldsighandler );
@@ -1228,13 +1248,14 @@ pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
1228
1248
{
1229
1249
sigset_t sigpipe_sigset ;
1230
1250
sigset_t sigset ;
1231
- int ret ;
1232
1251
1233
1252
sigemptyset (& sigpipe_sigset );
1234
1253
sigaddset (& sigpipe_sigset , SIGPIPE );
1235
1254
1236
1255
/* Block SIGPIPE and save previous mask for later reset */
1237
- ret = pthread_sigmask (SIG_BLOCK , & sigpipe_sigset , osigset );
1256
+ SOCK_ERRNO_SET (pthread_sigmask (SIG_BLOCK , & sigpipe_sigset , osigset ));
1257
+ if (SOCK_ERRNO )
1258
+ return -1 ;
1238
1259
1239
1260
/* We can have a pending SIGPIPE only if it was blocked before */
1240
1261
if (sigismember (osigset , SIGPIPE ))
@@ -1251,44 +1272,52 @@ pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
1251
1272
else
1252
1273
* sigpipe_pending = false;
1253
1274
1254
- return ret ;
1275
+ return 0 ;
1255
1276
}
1256
1277
1257
1278
/*
1258
1279
* 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.
1280
+ *
1281
+ * Note: we are effectively assuming here that the C library doesn't queue
1282
+ * up multiple SIGPIPE events. If it did, then we'd accidentally leave
1283
+ * ours in the queue when an event was already pending and we got another.
1284
+ * As long as it doesn't queue multiple events, we're OK because the caller
1285
+ * can't tell the difference.
1286
+ *
1287
+ * The caller should say got_epipe = FALSE if it is certain that it
1288
+ * didn't get an EPIPE error; in that case we'll skip the clear operation
1289
+ * and things are definitely OK, queuing or no. If it got one or might have
1290
+ * gotten one, pass got_epipe = TRUE.
1291
+ *
1292
+ * We do not want this to change errno, since if it did that could lose
1293
+ * the error code from a preceding send(). We essentially assume that if
1294
+ * we were able to do pq_block_sigpipe(), this can't fail.
1262
1295
*/
1263
- int
1264
- pq_reset_sigpipe (sigset_t * osigset , bool sigpipe_pending )
1296
+ void
1297
+ pq_reset_sigpipe (sigset_t * osigset , bool sigpipe_pending , bool got_epipe )
1265
1298
{
1299
+ int save_errno = SOCK_ERRNO ;
1266
1300
int signo ;
1267
1301
sigset_t sigset ;
1268
1302
1269
1303
/* Clear SIGPIPE only if none was pending */
1270
- if (!sigpipe_pending )
1304
+ if (got_epipe && !sigpipe_pending )
1271
1305
{
1272
- if (sigpending (& sigset ) != 0 )
1273
- return -1 ;
1274
-
1275
- /*
1276
- * Discard pending and blocked SIGPIPE
1277
- */
1278
- if (sigismember (& sigset , SIGPIPE ))
1306
+ if (sigpending (& sigset ) == 0 &&
1307
+ sigismember (& sigset , SIGPIPE ))
1279
1308
{
1280
1309
sigset_t sigpipe_sigset ;
1281
1310
1282
1311
sigemptyset (& sigpipe_sigset );
1283
1312
sigaddset (& sigpipe_sigset , SIGPIPE );
1284
-
1313
+
1285
1314
sigwait (& sigpipe_sigset , & signo );
1286
- if (signo != SIGPIPE )
1287
- return -1 ;
1288
1315
}
1289
1316
}
1290
1317
1291
1318
/* Restore saved block mask */
1292
- return pthread_sigmask (SIG_SETMASK , osigset , NULL );
1319
+ pthread_sigmask (SIG_SETMASK , osigset , NULL );
1320
+
1321
+ SOCK_ERRNO_SET (save_errno );
1293
1322
}
1294
1323
#endif
0 commit comments