22
22
* if it did much with shared memory then it would be prone to crashing
23
23
* along with the backends.
24
24
*
25
+ * When a request message is received, we now fork() immediately.
26
+ * The child process performs authentication of the request, and
27
+ * then becomes a backend if successful. This allows the auth code
28
+ * to be written in a simple single-threaded style (as opposed to the
29
+ * crufty "poor man's multitasking" code that used to be needed).
30
+ * More importantly, it ensures that blockages in non-multithreaded
31
+ * libraries like SSL or PAM cannot cause denial of service to other
32
+ * clients.
33
+ *
25
34
*
26
35
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
27
36
* Portions Copyright (c) 1994, Regents of the University of California
28
37
*
29
38
*
30
39
* IDENTIFICATION
31
- * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.224 2001/06/20 18:07:55 petere Exp $
40
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.225 2001/06/21 16:43:24 tgl Exp $
32
41
*
33
42
* NOTES
34
43
*
102
111
#ifdef HAVE_SIGPROCMASK
103
112
sigset_t UnBlockSig ,
104
113
BlockSig ;
105
-
106
114
#else
107
115
int UnBlockSig ,
108
116
BlockSig ;
109
-
110
117
#endif
111
118
112
119
/*
113
- * Info for garbage collection. Whenever a process dies, the Postmaster
114
- * cleans up after it. Currently, NO information is required for cleanup,
115
- * but I left this structure around in case that changed.
120
+ * List of active backends (or child processes anyway; we don't actually
121
+ * know whether a given child has become a backend or is still in the
122
+ * authorization phase). This is used mainly to keep track of how many
123
+ * children we have and send them appropriate signals when necessary.
116
124
*/
117
125
typedef struct bkend
118
126
{
119
127
pid_t pid ; /* process id of backend */
120
128
long cancel_key ; /* cancel key for cancels for this backend */
121
129
} Backend ;
122
130
123
- /* list of active backends. For garbage collection only now. */
124
131
static Dllist * BackendList ;
125
132
126
133
/* The socket number we are listening for connections on */
@@ -155,12 +162,10 @@ static int ServerSock_INET = INVALID_SOCK; /* stream socket server */
155
162
156
163
#ifdef HAVE_UNIX_SOCKETS
157
164
static int ServerSock_UNIX = INVALID_SOCK ; /* stream socket server */
158
-
159
165
#endif
160
166
161
167
#ifdef USE_SSL
162
168
static SSL_CTX * SSL_context = NULL ; /* Global SSL context */
163
-
164
169
#endif
165
170
166
171
/*
@@ -178,12 +183,14 @@ static char ExtraOptions[MAXPGPATH];
178
183
static bool Reinit = true;
179
184
static int SendStop = false;
180
185
186
+ /* still more option variables */
181
187
bool NetServer = false; /* listen on TCP/IP */
182
188
bool EnableSSL = false;
183
189
bool SilentMode = false; /* silent mode (-S) */
184
190
185
191
int CheckPointTimeout = 300 ;
186
192
193
+ /* Startup/shutdown state */
187
194
static pid_t StartupPID = 0 ,
188
195
ShutdownPID = 0 ,
189
196
CheckPointPID = 0 ;
@@ -230,7 +237,7 @@ static void ExitPostmaster(int status);
230
237
static void usage (const char * );
231
238
static int ServerLoop (void );
232
239
static int BackendStartup (Port * port );
233
- static int ProcessStartupPacket (Port * port );
240
+ static int ProcessStartupPacket (Port * port , bool SSLdone );
234
241
static void processCancelRequest (Port * port , void * pkt );
235
242
static int initMasks (fd_set * rmask , fd_set * wmask );
236
243
static char * canAcceptConnections (void );
@@ -579,6 +586,20 @@ PostmasterMain(int argc, char *argv[])
579
586
fprintf (stderr , "-----------------------------------------\n" );
580
587
}
581
588
589
+ /*
590
+ * Initialize SSL library, if specified.
591
+ */
592
+ #ifdef USE_SSL
593
+ if (EnableSSL && !NetServer )
594
+ {
595
+ postmaster_error ("For SSL, TCP/IP connections must be enabled." );
596
+ fprintf (stderr , gettext ("Try '%s --help' for more information.\n" ), progname );
597
+ ExitPostmaster (1 );
598
+ }
599
+ if (EnableSSL )
600
+ InitSSL ();
601
+ #endif
602
+
582
603
/*
583
604
* Fork away from controlling terminal, if -S specified.
584
605
*
@@ -609,17 +630,6 @@ PostmasterMain(int argc, char *argv[])
609
630
/*
610
631
* Establish input sockets.
611
632
*/
612
- #ifdef USE_SSL
613
- if (EnableSSL && !NetServer )
614
- {
615
- postmaster_error ("For SSL, TCP/IP connections must be enabled." );
616
- fprintf (stderr , gettext ("Try '%s --help' for more information.\n" ), progname );
617
- ExitPostmaster (1 );
618
- }
619
- if (EnableSSL )
620
- InitSSL ();
621
- #endif
622
-
623
633
if (NetServer )
624
634
{
625
635
status = StreamServerPort (AF_INET , VirtualHost ,
@@ -653,8 +663,7 @@ PostmasterMain(int argc, char *argv[])
653
663
reset_shared (PostPortNumber );
654
664
655
665
/*
656
- * Initialize the list of active backends. This list is only used for
657
- * garbage collecting the backend processes.
666
+ * Initialize the list of active backends.
658
667
*/
659
668
BackendList = DLNewList ();
660
669
@@ -811,7 +820,6 @@ ServerLoop(void)
811
820
812
821
if (CheckPointTimeout + checkpointed > now )
813
822
{
814
-
815
823
/*
816
824
* Not time for checkpoint yet, so set a timeout for
817
825
* select
@@ -883,7 +891,8 @@ ServerLoop(void)
883
891
}
884
892
885
893
/*
886
- * new connection pending on our well-known port's socket?
894
+ * New connection pending on our well-known port's socket?
895
+ * If so, fork a child process to deal with it.
887
896
*/
888
897
889
898
#ifdef HAVE_UNIX_SOCKETS
@@ -892,9 +901,15 @@ ServerLoop(void)
892
901
{
893
902
port = ConnCreate (ServerSock_UNIX );
894
903
if (port )
904
+ {
895
905
BackendStartup (port );
896
- StreamClose (port -> sock );
897
- ConnFree (port );
906
+ /*
907
+ * We no longer need the open socket or port structure
908
+ * in this process
909
+ */
910
+ StreamClose (port -> sock );
911
+ ConnFree (port );
912
+ }
898
913
}
899
914
#endif
900
915
@@ -903,9 +918,15 @@ ServerLoop(void)
903
918
{
904
919
port = ConnCreate (ServerSock_INET );
905
920
if (port )
921
+ {
906
922
BackendStartup (port );
907
- StreamClose (port -> sock );
908
- ConnFree (port );
923
+ /*
924
+ * We no longer need the open socket or port structure
925
+ * in this process
926
+ */
927
+ StreamClose (port -> sock );
928
+ ConnFree (port );
929
+ }
909
930
}
910
931
}
911
932
}
@@ -952,7 +973,7 @@ initMasks(fd_set *rmask, fd_set *wmask)
952
973
* not return at all.
953
974
*/
954
975
static int
955
- ProcessStartupPacket (Port * port )
976
+ ProcessStartupPacket (Port * port , bool SSLdone )
956
977
{
957
978
StartupPacket * packet ;
958
979
char * rejectMsg ;
@@ -983,7 +1004,7 @@ ProcessStartupPacket(Port *port)
983
1004
return 127 ; /* XXX */
984
1005
}
985
1006
986
- if (port -> proto == NEGOTIATE_SSL_CODE )
1007
+ if (port -> proto == NEGOTIATE_SSL_CODE && ! SSLdone )
987
1008
{
988
1009
char SSLok ;
989
1010
@@ -1016,10 +1037,9 @@ ProcessStartupPacket(Port *port)
1016
1037
}
1017
1038
}
1018
1039
#endif
1019
- /* regular startup packet should follow... */
1020
- /* FIXME: by continuing to send SSL negotiation packets, a
1021
- client could run us out of stack space */
1022
- return ProcessStartupPacket (port );
1040
+ /* regular startup packet, cancel, etc packet should follow... */
1041
+ /* but not another SSL negotiation request */
1042
+ return ProcessStartupPacket (port , true);
1023
1043
}
1024
1044
1025
1045
/* Could add additional special packet types here */
@@ -1211,11 +1231,8 @@ ConnFree(Port *conn)
1211
1231
* ClosePostmasterPorts -- close all the postmaster's open sockets
1212
1232
*
1213
1233
* This is called during child process startup to release file descriptors
1214
- * that are not needed by that child process.
1215
- *
1216
- * Note that closing the child's descriptor does not destroy the client
1217
- * connection prematurely, since the parent (postmaster) process still
1218
- * has the socket open.
1234
+ * that are not needed by that child process. The postmaster still has
1235
+ * them open, of course.
1219
1236
*/
1220
1237
static void
1221
1238
ClosePostmasterPorts (void )
@@ -1685,9 +1702,7 @@ SignalChildren(int signal)
1685
1702
/*
1686
1703
* BackendStartup -- start backend process
1687
1704
*
1688
- * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK
1689
- * otherwise.
1690
- *
1705
+ * returns: STATUS_ERROR if the fork/exec failed, STATUS_OK otherwise.
1691
1706
*/
1692
1707
static int
1693
1708
BackendStartup (Port * port )
@@ -1814,7 +1829,8 @@ split_opts(char **argv, int *argcp, char *s)
1814
1829
}
1815
1830
1816
1831
/*
1817
- * DoBackend -- set up the backend's argument list and invoke backend main().
1832
+ * DoBackend -- perform authentication, and if successful, set up the
1833
+ * backend's argument list and invoke backend main().
1818
1834
*
1819
1835
* This used to perform an execv() but we no longer exec the backend;
1820
1836
* it's the same executable as the postmaster.
@@ -1849,6 +1865,9 @@ DoBackend(Port *port)
1849
1865
* Signal handlers setting is moved to tcop/postgres...
1850
1866
*/
1851
1867
1868
+ /* Close the postmaster's other sockets */
1869
+ ClosePostmasterPorts ();
1870
+
1852
1871
SetProcessingMode (InitProcessing );
1853
1872
1854
1873
/* Save port etc. for ps status */
@@ -1859,13 +1878,10 @@ DoBackend(Port *port)
1859
1878
1860
1879
whereToSendOutput = Remote ;
1861
1880
1862
- status = ProcessStartupPacket (port );
1881
+ status = ProcessStartupPacket (port , false );
1863
1882
if (status == 127 )
1864
1883
return 0 ; /* cancel request processed */
1865
1884
1866
- /* Close the postmaster's other sockets */
1867
- ClosePostmasterPorts ();
1868
-
1869
1885
/*
1870
1886
* Don't want backend to be able to see the postmaster random number
1871
1887
* generator state. We have to clobber the static random_seed *and*
0 commit comments