On Mon, May 9, 2016 at 4:17 PM, Michael Paquier <michael.paqu...@gmail.com> wrote: > On Tue, Mar 22, 2016 at 1:56 PM, Amit Kapila <amit.kapil...@gmail.com> wrote: >> So as far as I can see there are two ways to resolve this issue, one is to >> retry generation of dsm name if CreateFileMapping returns EACCES and second >> is to append data_dir name to dsm name as the same is done for main shared >> memory, that will avoid the error to occur. First approach has minor flaw >> that if CreateFileMapping returns EACCES due to reason other then duplicate >> dsm name which I am not sure is possible to identify, then we should report >> error instead try to regenerate the name >> >> Robert and or others, can you share your opinion on what is the best way to >> proceed for this issue. > > For my 2c here, the approach using GetSharedMemName to identify the > origin of a dynamic shared memory segment looks more solid in terms of > robustness and collision handling. Retrying a segment is never going > to be completely water-proof.
So, I have been hacking that a bit more and finished with the attached, which seem to address the issue here. Some of the code paths of dsm_impl.c are done in such a way that we can fail a dsm allocation and still continue to move on. I have taken that into account by using palloc_extended with NO_OOM. palloc instead of malloc is a good fit anyway to prevent leaks in error code paths. Thoughts? -- Michael
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c index 173b982..060d0cb 100644 --- a/src/backend/storage/ipc/dsm_impl.c +++ b/src/backend/storage/ipc/dsm_impl.c @@ -62,6 +62,7 @@ #include <sys/shm.h> #endif +#include "miscadmin.h" #include "portability/mem.h" #include "storage/dsm_impl.h" #include "storage/fd.h" @@ -80,6 +81,7 @@ static bool dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size, Size *mapped_size, int elevel); #endif #ifdef USE_DSM_WINDOWS +static char *get_segment_name(dsm_handle handle); static bool dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel); @@ -590,6 +592,36 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size, #ifdef USE_DSM_WINDOWS /* + * Generate shared memory segment name, using the data directory to generate + * a unique identifier. This segment is stored in Global\ namespace to allow + * any other process to have an access to it. + */ +static char * +get_segment_name(dsm_handle handle) +{ + char *res; + + /* let enough place for prefix and handle */ + res = palloc_extended(strlen(DataDir) + 64, MCXT_ALLOC_NO_OOM); + + if (res == NULL) + return NULL; + + /* + * Storing the shared memory segment in the Global\ namespace, can allow + * any process running in any session to access that file mapping object + * provided that the caller has the required access rights. But to avoid + * issues faced in main shared memory, we are using the naming convention + * similar to main shared memory. We can change here once issue mentioned + * in GetSharedMemName is resolved. + */ + snprintf(res, strlen(DataDir) + 64, "%s.%s.%u", + SEGMENT_NAME_PREFIX, DataDir, handle); + + return res; +} + +/* * Operating system primitives to support Windows shared memory. * * Windows shared memory implementation is done using file mapping @@ -609,7 +641,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, { char *address; HANDLE hmap; - char name[64]; + char *name; MEMORY_BASIC_INFORMATION info; /* Resize is not supported for Windows shared memory. */ @@ -623,15 +655,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, if (op == DSM_OP_ATTACH && *mapped_address != NULL) return true; - /* - * Storing the shared memory segment in the Global\ namespace, can allow - * any process running in any session to access that file mapping object - * provided that the caller has the required access rights. But to avoid - * issues faced in main shared memory, we are using the naming convention - * similar to main shared memory. We can change here once issue mentioned - * in GetSharedMemName is resolved. - */ - snprintf(name, 64, "%s.%u", SEGMENT_NAME_PREFIX, handle); + name = get_segment_name(handle); + + if (name == NULL) + { + elog(elevel, "could not allocate memory for shared memory segment name"); + return false; + } /* * Handle teardown cases. Since Windows automatically destroys the object @@ -647,6 +677,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, (errcode_for_dynamic_shared_memory(), errmsg("could not unmap shared memory segment \"%s\": %m", name))); + pfree(name); return false; } if (*impl_private != NULL @@ -657,12 +688,14 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, (errcode_for_dynamic_shared_memory(), errmsg("could not remove shared memory segment \"%s\": %m", name))); + pfree(name); return false; } *impl_private = NULL; *mapped_address = NULL; *mapped_size = 0; + pfree(name); return true; } @@ -693,6 +726,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, (errcode_for_dynamic_shared_memory(), errmsg("could not create shared memory segment \"%s\": %m", name))); + pfree(name); return false; } _dosmaperr(GetLastError()); @@ -705,6 +739,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, * modified. */ CloseHandle(hmap); + pfree(name); return false; } } @@ -720,6 +755,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, (errcode_for_dynamic_shared_memory(), errmsg("could not open shared memory segment \"%s\": %m", name))); + pfree(name); return false; } } @@ -741,6 +777,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, (errcode_for_dynamic_shared_memory(), errmsg("could not map shared memory segment \"%s\": %m", name))); + pfree(name); return false; } @@ -765,6 +802,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, (errcode_for_dynamic_shared_memory(), errmsg("could not stat shared memory segment \"%s\": %m", name))); + pfree(name); return false; } @@ -772,6 +810,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, *mapped_size = info.RegionSize; *impl_private = hmap; + pfree(name); return true; } #endif @@ -1009,14 +1048,15 @@ dsm_impl_pin_segment(dsm_handle handle, void *impl_private) PostmasterHandle, &hmap, 0, FALSE, DUPLICATE_SAME_ACCESS)) { - char name[64]; + char *name; - snprintf(name, 64, "%s.%u", SEGMENT_NAME_PREFIX, handle); _dosmaperr(GetLastError()); + name = get_segment_name(handle); ereport(ERROR, (errcode_for_dynamic_shared_memory(), errmsg("could not duplicate handle for \"%s\": %m", - name))); + name ? name : "undefined"))); + pfree(name); } break; }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers