112
112
#include "postmaster/autovacuum.h"
113
113
#include "postmaster/bgworker_internals.h"
114
114
#include "postmaster/fork_process.h"
115
+ #include "postmaster/interrupt.h"
115
116
#include "postmaster/pgarch.h"
116
117
#include "postmaster/postmaster.h"
117
118
#include "postmaster/syslogger.h"
@@ -401,7 +402,7 @@ static void SIGHUP_handler(SIGNAL_ARGS);
401
402
static void pmdie (SIGNAL_ARGS );
402
403
static void reaper (SIGNAL_ARGS );
403
404
static void sigusr1_handler (SIGNAL_ARGS );
404
- static void startup_die (SIGNAL_ARGS );
405
+ static void process_startup_packet_die (SIGNAL_ARGS );
405
406
static void dummy_handler (SIGNAL_ARGS );
406
407
static void StartupPacketTimeoutHandler (void );
407
408
static void CleanupBackend (int pid , int exitstatus );
@@ -4337,22 +4338,30 @@ BackendInitialize(Port *port)
4337
4338
whereToSendOutput = DestRemote ; /* now safe to ereport to client */
4338
4339
4339
4340
/*
4340
- * We arrange for a simple exit(1) if we receive SIGTERM or SIGQUIT or
4341
- * timeout while trying to collect the startup packet. Otherwise the
4342
- * postmaster cannot shutdown the database FAST or IMMED cleanly if a
4343
- * buggy client fails to send the packet promptly. XXX it follows that
4344
- * the remainder of this function must tolerate losing control at any
4345
- * instant. Likewise, any pg_on_exit_callback registered before or during
4346
- * this function must be prepared to execute at any instant between here
4347
- * and the end of this function. Furthermore, affected callbacks execute
4348
- * partially or not at all when a second exit-inducing signal arrives
4349
- * after proc_exit_prepare() decrements on_proc_exit_index. (Thanks to
4350
- * that mechanic, callbacks need not anticipate more than one call.) This
4351
- * is fragile; it ought to instead follow the norm of handling interrupts
4352
- * at selected, safe opportunities.
4353
- */
4354
- pqsignal (SIGTERM , startup_die );
4355
- pqsignal (SIGQUIT , startup_die );
4341
+ * We arrange to do proc_exit(1) if we receive SIGTERM or timeout while
4342
+ * trying to collect the startup packet; while SIGQUIT results in
4343
+ * _exit(2). Otherwise the postmaster cannot shutdown the database FAST
4344
+ * or IMMED cleanly if a buggy client fails to send the packet promptly.
4345
+ *
4346
+ * XXX this is pretty dangerous; signal handlers should not call anything
4347
+ * as complex as proc_exit() directly. We minimize the hazard by not
4348
+ * keeping these handlers active for longer than we must. However, it
4349
+ * seems necessary to be able to escape out of DNS lookups as well as the
4350
+ * startup packet reception proper, so we can't narrow the scope further
4351
+ * than is done here.
4352
+ *
4353
+ * XXX it follows that the remainder of this function must tolerate losing
4354
+ * control at any instant. Likewise, any pg_on_exit_callback registered
4355
+ * before or during this function must be prepared to execute at any
4356
+ * instant between here and the end of this function. Furthermore,
4357
+ * affected callbacks execute partially or not at all when a second
4358
+ * exit-inducing signal arrives after proc_exit_prepare() decrements
4359
+ * on_proc_exit_index. (Thanks to that mechanic, callbacks need not
4360
+ * anticipate more than one call.) This is fragile; it ought to instead
4361
+ * follow the norm of handling interrupts at selected, safe opportunities.
4362
+ */
4363
+ pqsignal (SIGTERM , process_startup_packet_die );
4364
+ pqsignal (SIGQUIT , SignalHandlerForCrashExit );
4356
4365
InitializeTimeouts (); /* establishes SIGALRM handler */
4357
4366
PG_SETMASK (& StartupBlockSig );
4358
4367
@@ -4408,8 +4417,8 @@ BackendInitialize(Port *port)
4408
4417
port -> remote_hostname = strdup (remote_host );
4409
4418
4410
4419
/*
4411
- * Ready to begin client interaction. We will give up and exit (1) after a
4412
- * time delay, so that a broken client can't hog a connection
4420
+ * Ready to begin client interaction. We will give up and proc_exit (1)
4421
+ * after a time delay, so that a broken client can't hog a connection
4413
4422
* indefinitely. PreAuthDelay and any DNS interactions above don't count
4414
4423
* against the time limit.
4415
4424
*
@@ -4431,6 +4440,12 @@ BackendInitialize(Port *port)
4431
4440
*/
4432
4441
status = ProcessStartupPacket (port , false, false);
4433
4442
4443
+ /*
4444
+ * Disable the timeout, and prevent SIGTERM/SIGQUIT again.
4445
+ */
4446
+ disable_timeout (STARTUP_PACKET_TIMEOUT , false);
4447
+ PG_SETMASK (& BlockSig );
4448
+
4434
4449
/*
4435
4450
* Stop here if it was bad or a cancel packet. ProcessStartupPacket
4436
4451
* already did any appropriate error reporting.
@@ -4456,12 +4471,6 @@ BackendInitialize(Port *port)
4456
4471
pfree (ps_data .data );
4457
4472
4458
4473
set_ps_display ("initializing" );
4459
-
4460
- /*
4461
- * Disable the timeout, and prevent SIGTERM/SIGQUIT again.
4462
- */
4463
- disable_timeout (STARTUP_PACKET_TIMEOUT , false);
4464
- PG_SETMASK (& BlockSig );
4465
4474
}
4466
4475
4467
4476
@@ -5351,16 +5360,22 @@ sigusr1_handler(SIGNAL_ARGS)
5351
5360
}
5352
5361
5353
5362
/*
5354
- * SIGTERM or SIGQUIT while processing startup packet.
5363
+ * SIGTERM while processing startup packet.
5355
5364
* Clean up and exit(1).
5356
5365
*
5357
- * XXX: possible future improvement: try to send a message indicating
5358
- * why we are disconnecting. Problem is to be sure we don't block while
5359
- * doing so, nor mess up SSL initialization. In practice, if the client
5360
- * has wedged here, it probably couldn't do anything with the message anyway.
5366
+ * Running proc_exit() from a signal handler is pretty unsafe, since we
5367
+ * can't know what code we've interrupted. But the alternative of using
5368
+ * _exit(2) is also unpalatable, since it'd mean that a "fast shutdown"
5369
+ * would cause a database crash cycle (forcing WAL replay at restart)
5370
+ * if any sessions are in authentication. So we live with it for now.
5371
+ *
5372
+ * One might be tempted to try to send a message indicating why we are
5373
+ * disconnecting. However, that would make this even more unsafe. Also,
5374
+ * it seems undesirable to provide clues about the database's state to
5375
+ * a client that has not yet completed authentication.
5361
5376
*/
5362
5377
static void
5363
- startup_die (SIGNAL_ARGS )
5378
+ process_startup_packet_die (SIGNAL_ARGS )
5364
5379
{
5365
5380
proc_exit (1 );
5366
5381
}
@@ -5381,7 +5396,11 @@ dummy_handler(SIGNAL_ARGS)
5381
5396
5382
5397
/*
5383
5398
* Timeout while processing startup packet.
5384
- * As for startup_die(), we clean up and exit(1).
5399
+ * As for process_startup_packet_die(), we clean up and exit(1).
5400
+ *
5401
+ * This is theoretically just as hazardous as in process_startup_packet_die(),
5402
+ * although in practice we're almost certainly waiting for client input,
5403
+ * which greatly reduces the risk.
5385
5404
*/
5386
5405
static void
5387
5406
StartupPacketTimeoutHandler (void )
0 commit comments