10
10
* Portions Copyright (c) 1994, Regents of the University of California
11
11
*
12
12
* IDENTIFICATION
13
- * $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.8 2003/05/06 23:34:55 momjian Exp $
13
+ * $Header: /cvsroot/pgsql/src/backend/port/sysv_shmem.c,v 1.9 2003/05/08 14:49:03 momjian Exp $
14
14
*
15
15
*-------------------------------------------------------------------------
16
16
*/
@@ -39,9 +39,8 @@ typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */
39
39
#define IPCProtection (0600) /* access/modify by user only */
40
40
41
41
42
- #ifdef EXEC_BACKEND
43
42
IpcMemoryKey UsedShmemSegID = 0 ;
44
- #endif
43
+ void * UsedShmemSegAddr = NULL ;
45
44
46
45
static void * InternalIpcMemoryCreate (IpcMemoryKey memKey , uint32 size );
47
46
static void IpcMemoryDetach (int status , Datum shmaddr );
@@ -282,7 +281,7 @@ PrivateMemoryDelete(int status, Datum memaddr)
282
281
*
283
282
* Create a shared memory segment of the given size and initialize its
284
283
* standard header. Also, register an on_shmem_exit callback to release
285
- * the storage.
284
+ * the storage. For an exec'ed backend, it just attaches.
286
285
*
287
286
* Dead Postgres segments are recycled if found, but we do not fail upon
288
287
* collision with non-Postgres shmem segments. The idea here is to detect and
@@ -302,11 +301,9 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
302
301
/* Room for a header? */
303
302
Assert (size > MAXALIGN (sizeof (PGShmemHeader )));
304
303
305
- #ifdef EXEC_BACKEND
306
- if (UsedShmemSegID != 0 )
304
+ if (ExecBackend && UsedShmemSegID != 0 )
307
305
NextShmemSegID = UsedShmemSegID ;
308
306
else
309
- #endif
310
307
NextShmemSegID = port * 1000 + 1 ;
311
308
312
309
for (;;NextShmemSegID ++ )
@@ -320,40 +317,59 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
320
317
break ;
321
318
}
322
319
323
- /* Try to create new segment */
324
- memAddress = InternalIpcMemoryCreate (NextShmemSegID , size );
325
- if (memAddress )
326
- break ; /* successful create and attach */
320
+ /* If attach to fixed address, only try once */
321
+ if (ExecBackend && UsedShmemSegAddr != NULL && NextShmemSegID != UsedShmemSegID )
322
+ {
323
+ fprintf (stderr , "Unable to attach to memory at fixed address: shmget(key=%d, addr=%p) failed: %s\n" ,
324
+ (int ) UsedShmemSegID , UsedShmemSegAddr , strerror (errno ));
325
+ proc_exit (1 );
326
+ }
327
+
328
+ if (!ExecBackend || UsedShmemSegAddr == NULL )
329
+ {
330
+ /* Try to create new segment */
331
+ memAddress = InternalIpcMemoryCreate (NextShmemSegID , size );
332
+ if (memAddress )
333
+ break ; /* successful create and attach */
334
+ }
327
335
328
336
/* See if it looks to be leftover from a dead Postgres process */
329
337
shmid = shmget (NextShmemSegID , sizeof (PGShmemHeader ), 0 );
330
338
if (shmid < 0 )
331
339
continue ; /* failed: must be some other app's */
332
340
333
- #if defined(solaris ) && defined(__sparc__ )
334
341
/* use intimate shared memory on SPARC Solaris */
335
- memAddress = shmat (shmid , 0 , SHM_SHARE_MMU );
342
+ memAddress = shmat (shmid , UsedShmemSegAddr ,
343
+ #if defined(solaris ) && defined (__sparc__ )
344
+ SHM_SHARE_MMU
336
345
#else
337
- memAddress = shmat ( shmid , 0 , 0 );
346
+ 0
338
347
#endif
348
+ );
339
349
340
350
if (memAddress == (void * ) -1 )
341
351
continue ; /* failed: must be some other app's */
352
+
342
353
hdr = (PGShmemHeader * ) memAddress ;
343
354
if (hdr -> magic != PGShmemMagic )
344
355
{
345
356
shmdt (memAddress );
346
357
continue ; /* segment belongs to a non-Postgres app */
347
358
}
348
359
360
+ /* Successfully attached to shared memory, which is all we wanted */
361
+ if (ExecBackend && UsedShmemSegAddr != NULL )
362
+ break ;
363
+
364
+ /* Check shared memory and possibly remove and recreate */
365
+
349
366
/*
350
- * If the creator PID is my own PID or does not belong to any
351
- * extant process, it's safe to zap it .
367
+ * If I am not the creator and it belongs to an extant process,
368
+ * continue .
352
369
*/
353
370
if (hdr -> creatorPID != getpid ())
354
371
{
355
- if (kill (hdr -> creatorPID , 0 ) == 0 ||
356
- errno != ESRCH )
372
+ if (kill (hdr -> creatorPID , 0 ) == 0 || errno != ESRCH )
357
373
{
358
374
shmdt (memAddress );
359
375
continue ; /* segment belongs to a live process */
@@ -385,26 +401,31 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
385
401
*/
386
402
}
387
403
388
- /*
389
- * OK, we created a new segment. Mark it as created by this process.
390
- * The order of assignments here is critical so that another Postgres
391
- * process can't see the header as valid but belonging to an invalid
392
- * PID!
393
- */
394
404
hdr = (PGShmemHeader * ) memAddress ;
395
- hdr -> creatorPID = getpid ();
396
- hdr -> magic = PGShmemMagic ;
397
405
398
- /*
399
- * Initialize space allocation status for segment.
400
- */
401
- hdr -> totalsize = size ;
402
- hdr -> freeoffset = MAXALIGN (sizeof (PGShmemHeader ));
406
+ if (!ExecBackend || makePrivate || UsedShmemSegAddr == NULL )
407
+ {
408
+ /*
409
+ * OK, we created a new segment. Mark it as created by this process.
410
+ * The order of assignments here is critical so that another Postgres
411
+ * process can't see the header as valid but belonging to an invalid
412
+ * PID!
413
+ */
414
+ hdr -> creatorPID = getpid ();
415
+ hdr -> magic = PGShmemMagic ;
416
+
417
+ /*
418
+ * Initialize space allocation status for segment.
419
+ */
420
+ hdr -> totalsize = size ;
421
+ hdr -> freeoffset = MAXALIGN (sizeof (PGShmemHeader ));
422
+ }
403
423
404
- #ifdef EXEC_BACKEND
405
- if (!makePrivate && UsedShmemSegID == 0 )
424
+ if (ExecBackend && !makePrivate && UsedShmemSegAddr == NULL )
425
+ {
426
+ UsedShmemSegAddr = memAddress ;
406
427
UsedShmemSegID = NextShmemSegID ;
407
- #endif
428
+ }
408
429
409
430
return hdr ;
410
431
}
0 commit comments