8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.105 2001/09/04 02:26:57 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.106 2001/09/04 21:42:17 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -186,6 +186,17 @@ InitProcess(void)
186
186
unsigned long location ,
187
187
myOffset ;
188
188
189
+ /*
190
+ * ProcStructLock protects the freelist of PROC entries and the map
191
+ * of free semaphores. Note that when we acquire it here, we do not
192
+ * have a PROC entry and so the ownership of the spinlock is not
193
+ * recorded anywhere; even if it was, until we register ProcKill as
194
+ * an on_shmem_exit callback, there is no exit hook that will cause
195
+ * owned spinlocks to be released. Upshot: during the first part of
196
+ * this routine, be careful to release the lock manually before any
197
+ * elog(), else you'll have a stuck spinlock to add to your woes.
198
+ */
199
+
189
200
SpinAcquire (ProcStructLock );
190
201
191
202
/* attach to the ProcGlobal structure */
@@ -194,13 +205,14 @@ InitProcess(void)
194
205
if (!found )
195
206
{
196
207
/* this should not happen. InitProcGlobal() is called before this. */
208
+ SpinRelease (ProcStructLock );
197
209
elog (STOP , "InitProcess: Proc Header uninitialized" );
198
210
}
199
211
200
212
if (MyProc != NULL )
201
213
{
202
214
SpinRelease (ProcStructLock );
203
- elog (ERROR , "ProcInit : you already exist" );
215
+ elog (ERROR , "InitProcess : you already exist" );
204
216
}
205
217
206
218
/* try to get a proc struct from the free list first */
@@ -214,14 +226,12 @@ InitProcess(void)
214
226
}
215
227
else
216
228
{
217
-
218
229
/*
219
230
* have to allocate one. We can't use the normal shmem index
220
231
* table mechanism because the proc structure is stored by PID
221
232
* instead of by a global name (need to look it up by PID when we
222
233
* cleanup dead processes).
223
234
*/
224
-
225
235
MyProc = (PROC * ) ShmemAlloc (sizeof (PROC ));
226
236
if (!MyProc )
227
237
{
@@ -231,44 +241,32 @@ InitProcess(void)
231
241
}
232
242
233
243
/*
234
- * zero out the spin lock counts and set the sLocks field for
235
- * ProcStructLock to 1 as we have acquired this spinlock above but
236
- * didn't record it since we didn't have MyProc until now.
237
- */
238
- MemSet (MyProc -> sLocks , 0 , sizeof (MyProc -> sLocks ));
239
- MyProc -> sLocks [ProcStructLock ] = 1 ;
240
-
241
- /*
242
- * Set up a wait-semaphore for the proc.
244
+ * Initialize all fields of MyProc.
243
245
*/
244
- if (IsUnderPostmaster )
245
- {
246
- ProcGetNewSemIdAndNum (& MyProc -> sem .semId , & MyProc -> sem .semNum );
247
-
248
- /*
249
- * we might be reusing a semaphore that belongs to a dead backend.
250
- * So be careful and reinitialize its value here.
251
- */
252
- ZeroProcSemaphore (MyProc );
253
- }
254
- else
255
- {
256
- MyProc -> sem .semId = -1 ;
257
- MyProc -> sem .semNum = -1 ;
258
- }
259
-
260
246
SHMQueueElemInit (& (MyProc -> links ));
247
+ MyProc -> sem .semId = -1 ; /* no wait-semaphore acquired yet */
248
+ MyProc -> sem .semNum = -1 ;
261
249
MyProc -> errType = STATUS_OK ;
262
- MyProc -> pid = MyProcPid ;
263
- MyProc -> databaseId = MyDatabaseId ;
264
250
MyProc -> xid = InvalidTransactionId ;
265
251
MyProc -> xmin = InvalidTransactionId ;
252
+ MyProc -> logRec .xrecoff = 0 ;
266
253
MyProc -> waitLock = NULL ;
267
254
MyProc -> waitHolder = NULL ;
255
+ MyProc -> pid = MyProcPid ;
256
+ MyProc -> databaseId = MyDatabaseId ;
268
257
SHMQueueInit (& (MyProc -> procHolders ));
258
+ /*
259
+ * Zero out the spin lock counts and set the sLocks field for
260
+ * ProcStructLock to 1 as we have acquired this spinlock above but
261
+ * didn't record it since we didn't have MyProc until now.
262
+ */
263
+ MemSet (MyProc -> sLocks , 0 , sizeof (MyProc -> sLocks ));
264
+ MyProc -> sLocks [ProcStructLock ] = 1 ;
269
265
270
266
/*
271
- * Release the lock.
267
+ * Release the lock while accessing shmem index; we still haven't
268
+ * installed ProcKill and so we don't want to hold lock if there's
269
+ * an error.
272
270
*/
273
271
SpinRelease (ProcStructLock );
274
272
@@ -283,10 +281,28 @@ InitProcess(void)
283
281
elog (STOP , "InitProcess: ShmemPID table broken" );
284
282
285
283
/*
286
- * Arrange to clean up at backend exit.
284
+ * Arrange to clean up at backend exit. Once we do this, owned
285
+ * spinlocks will be released on exit, and so we can be a lot less
286
+ * tense about errors.
287
287
*/
288
288
on_shmem_exit (ProcKill , 0 );
289
289
290
+ /*
291
+ * Set up a wait-semaphore for the proc. (Do this last so that we
292
+ * can rely on ProcKill to clean up if it fails.)
293
+ */
294
+ if (IsUnderPostmaster )
295
+ {
296
+ SpinAcquire (ProcStructLock );
297
+ ProcGetNewSemIdAndNum (& MyProc -> sem .semId , & MyProc -> sem .semNum );
298
+ SpinRelease (ProcStructLock );
299
+ /*
300
+ * We might be reusing a semaphore that belongs to a dead backend.
301
+ * So be careful and reinitialize its value here.
302
+ */
303
+ ZeroProcSemaphore (MyProc );
304
+ }
305
+
290
306
/*
291
307
* Now that we have a PROC, we could try to acquire locks, so
292
308
* initialize the deadlock checker.
@@ -425,8 +441,9 @@ ProcKill(void)
425
441
426
442
SpinAcquire (ProcStructLock );
427
443
428
- /* Free up my wait semaphore */
429
- ProcFreeSem (MyProc -> sem .semId , MyProc -> sem .semNum );
444
+ /* Free up my wait semaphore, if I got one */
445
+ if (MyProc -> sem .semId >= 0 )
446
+ ProcFreeSem (MyProc -> sem .semId , MyProc -> sem .semNum );
430
447
431
448
/* Add PROC struct to freelist so space can be recycled in future */
432
449
MyProc -> links .next = ProcGlobal -> freeProcs ;
@@ -993,10 +1010,7 @@ ProcGetNewSemIdAndNum(IpcSemaphoreId *semId, int *semNum)
993
1010
{
994
1011
if ((freeSemMap [i ] & mask ) == 0 )
995
1012
{
996
-
997
- /*
998
- * a free semaphore found. Mark it as allocated.
999
- */
1013
+ /* A free semaphore found. Mark it as allocated. */
1000
1014
freeSemMap [i ] |= mask ;
1001
1015
1002
1016
* semId = procSemIds [i ];
@@ -1007,8 +1021,13 @@ ProcGetNewSemIdAndNum(IpcSemaphoreId *semId, int *semNum)
1007
1021
}
1008
1022
}
1009
1023
1010
- /* if we reach here, all the semaphores are in use. */
1011
- elog (ERROR , "ProcGetNewSemIdAndNum: cannot allocate a free semaphore" );
1024
+ /*
1025
+ * If we reach here, all the semaphores are in use. This is one of the
1026
+ * possible places to detect "too many backends", so give the standard
1027
+ * error message. (Whether we detect it here or in sinval.c depends on
1028
+ * whether MaxBackends is a multiple of PROC_NSEMS_PER_SET.)
1029
+ */
1030
+ elog (FATAL , "Sorry, too many clients already" );
1012
1031
}
1013
1032
1014
1033
/*
0 commit comments