|
16 | 16 | #include "storage/ipc.h"
|
17 | 17 | #include "storage/pg_shmem.h"
|
18 | 18 |
|
19 |
| -HANDLE UsedShmemSegID = 0; |
| 19 | +HANDLE UsedShmemSegID = INVALID_HANDLE_VALUE; |
20 | 20 | void *UsedShmemSegAddr = NULL;
|
21 | 21 | static Size UsedShmemSegSize = 0;
|
22 | 22 |
|
@@ -82,7 +82,6 @@ GetSharedMemName(void)
|
82 | 82 | * we only care about shmem segments that are associated with the intended
|
83 | 83 | * DataDir. This is an important consideration since accidental matches of
|
84 | 84 | * shmem segment IDs are reasonably common.
|
85 |
| - * |
86 | 85 | */
|
87 | 86 | bool
|
88 | 87 | PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
|
@@ -114,7 +113,6 @@ PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
|
114 | 113 | * or recycle any existing segment. On win32, we always create a new segment,
|
115 | 114 | * since there is no need for recycling (segments go away automatically
|
116 | 115 | * when the last backend exits)
|
117 |
| - * |
118 | 116 | */
|
119 | 117 | PGShmemHeader *
|
120 | 118 | PGSharedMemoryCreate(Size size, bool makePrivate, int port)
|
@@ -211,9 +209,6 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
|
211 | 209 | elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
|
212 | 210 |
|
213 | 211 |
|
214 |
| - /* Register on-exit routine to delete the new segment */ |
215 |
| - on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2)); |
216 |
| - |
217 | 212 | /*
|
218 | 213 | * Get a pointer to the new shared memory segment. Map the whole segment
|
219 | 214 | * at once, and let the system decide on the initial address.
|
@@ -246,14 +241,18 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
|
246 | 241 | UsedShmemSegSize = size;
|
247 | 242 | UsedShmemSegID = hmap2;
|
248 | 243 |
|
| 244 | + /* Register on-exit routine to delete the new segment */ |
| 245 | + on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2)); |
| 246 | + |
249 | 247 | return hdr;
|
250 | 248 | }
|
251 | 249 |
|
252 | 250 | /*
|
253 | 251 | * PGSharedMemoryReAttach
|
254 | 252 | *
|
255 |
| - * Re-attach to an already existing shared memory segment. Use the |
256 |
| - * handle inherited from the postmaster. |
| 253 | + * This is called during startup of a postmaster child process to re-attach to |
| 254 | + * an already existing shared memory segment, using the handle inherited from |
| 255 | + * the postmaster. |
257 | 256 | *
|
258 | 257 | * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this
|
259 | 258 | * routine. The caller must have already restored them to the postmaster's
|
@@ -288,37 +287,88 @@ PGSharedMemoryReAttach(void)
|
288 | 287 | UsedShmemSegAddr = hdr; /* probably redundant */
|
289 | 288 | }
|
290 | 289 |
|
| 290 | +/* |
| 291 | + * PGSharedMemoryNoReAttach |
| 292 | + * |
| 293 | + * This is called during startup of a postmaster child process when we choose |
| 294 | + * *not* to re-attach to the existing shared memory segment. We must clean up |
| 295 | + * to leave things in the appropriate state. |
| 296 | + * |
| 297 | + * The child process startup logic might or might not call PGSharedMemoryDetach |
| 298 | + * after this; make sure that it will be a no-op if called. |
| 299 | + * |
| 300 | + * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this |
| 301 | + * routine. The caller must have already restored them to the postmaster's |
| 302 | + * values. |
| 303 | + */ |
| 304 | +void |
| 305 | +PGSharedMemoryNoReAttach(void) |
| 306 | +{ |
| 307 | + Assert(UsedShmemSegAddr != NULL); |
| 308 | + Assert(IsUnderPostmaster); |
| 309 | + |
| 310 | + /* |
| 311 | + * Under Windows we will not have mapped the segment, so we don't need to |
| 312 | + * un-map it. Just reset UsedShmemSegAddr to show we're not attached. |
| 313 | + */ |
| 314 | + UsedShmemSegAddr = NULL; |
| 315 | + |
| 316 | + /* |
| 317 | + * We *must* close the inherited shmem segment handle, else Windows will |
| 318 | + * consider the existence of this process to mean it can't release the |
| 319 | + * shmem segment yet. We can now use PGSharedMemoryDetach to do that. |
| 320 | + */ |
| 321 | + PGSharedMemoryDetach(); |
| 322 | +} |
| 323 | + |
291 | 324 | /*
|
292 | 325 | * PGSharedMemoryDetach
|
293 | 326 | *
|
294 | 327 | * Detach from the shared memory segment, if still attached. This is not
|
295 |
| - * intended for use by the process that originally created the segment. Rather, |
296 |
| - * this is for subprocesses that have inherited an attachment and want to |
297 |
| - * get rid of it. |
| 328 | + * intended to be called explicitly by the process that originally created the |
| 329 | + * segment (it will have an on_shmem_exit callback registered to do that). |
| 330 | + * Rather, this is for subprocesses that have inherited an attachment and want |
| 331 | + * to get rid of it. |
| 332 | + * |
| 333 | + * UsedShmemSegID and UsedShmemSegAddr are implicit parameters to this |
| 334 | + * routine. |
298 | 335 | */
|
299 | 336 | void
|
300 | 337 | PGSharedMemoryDetach(void)
|
301 | 338 | {
|
| 339 | + /* Unmap the view, if it's mapped */ |
302 | 340 | if (UsedShmemSegAddr != NULL)
|
303 | 341 | {
|
304 | 342 | if (!UnmapViewOfFile(UsedShmemSegAddr))
|
305 |
| - elog(LOG, "could not unmap view of shared memory: error code %lu", GetLastError()); |
| 343 | + elog(LOG, "could not unmap view of shared memory: error code %lu", |
| 344 | + GetLastError()); |
306 | 345 |
|
307 | 346 | UsedShmemSegAddr = NULL;
|
308 | 347 | }
|
| 348 | + |
| 349 | + /* And close the shmem handle, if we have one */ |
| 350 | + if (UsedShmemSegID != INVALID_HANDLE_VALUE) |
| 351 | + { |
| 352 | + if (!CloseHandle(UsedShmemSegID)) |
| 353 | + elog(LOG, "could not close handle to shared memory: error code %lu", |
| 354 | + GetLastError()); |
| 355 | + |
| 356 | + UsedShmemSegID = INVALID_HANDLE_VALUE; |
| 357 | + } |
309 | 358 | }
|
310 | 359 |
|
311 | 360 |
|
312 | 361 | /*
|
313 |
| - * pgwin32_SharedMemoryDelete(status, shmId) deletes a shared memory segment |
314 |
| - * (called as an on_shmem_exit callback, hence funny argument list) |
| 362 | + * pgwin32_SharedMemoryDelete |
| 363 | + * |
| 364 | + * Detach from and delete the shared memory segment |
| 365 | + * (called as an on_shmem_exit callback, hence funny argument list) |
315 | 366 | */
|
316 | 367 | static void
|
317 | 368 | pgwin32_SharedMemoryDelete(int status, Datum shmId)
|
318 | 369 | {
|
| 370 | + Assert(DatumGetPointer(shmId) == UsedShmemSegID); |
319 | 371 | PGSharedMemoryDetach();
|
320 |
| - if (!CloseHandle(DatumGetPointer(shmId))) |
321 |
| - elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError()); |
322 | 372 | }
|
323 | 373 |
|
324 | 374 | /*
|
|
0 commit comments