Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed work with Shared Memory on Windows. #17273

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions TSRM/tsrm_win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,21 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
CloseHandle(shm_handle);
return -1;
}
shm->segment = shm_handle;
shm->descriptor = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
if (NULL == shm->segment || INVALID_HANDLE_VALUE == shm->segment) {
shm->segment = shm_handle;
shm->created = created;
}
else if (TRUE == created) {
CloseHandle(shm->segment);
shm->segment = shm_handle;
shm->created = TRUE;
}
Comment on lines +695 to +699
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what would be special about created. We either use OpenFileMapping() or CreateFileMapping() to get the shm_handle, and it seems to me that we want to close the shm->segment in neither case.

else {
CloseHandle(shm_handle);
}
if(NULL == shm->descriptor){
shm->descriptor = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
}

if (NULL != shm->descriptor && created) {
shm->descriptor->shm_perm.key = key;
Expand Down Expand Up @@ -730,6 +743,7 @@ TSRM_API void *shmat(int key, const void *shmaddr, int flags)
shm->descriptor->shm_atime = time(NULL);
shm->descriptor->shm_lpid = getpid();
shm->descriptor->shm_nattch++;
shm->shm_nattch++;

return shm->addr;
}/*}}}*/
Expand All @@ -746,12 +760,22 @@ TSRM_API int shmdt(const void *shmaddr)
shm->descriptor->shm_dtime = time(NULL);
shm->descriptor->shm_lpid = getpid();
shm->descriptor->shm_nattch--;
shm->shm_nattch--;

ret = 0;
if (shm->descriptor->shm_nattch <= 0) {
ret = UnmapViewOfFile(shm->descriptor) ? 0 : -1;
shm->descriptor = NULL;
if (shm->shm_nattch <= 0) {
shm->shm_nattch = 0;
if (NULL != shm->segment && INVALID_HANDLE_VALUE != shm->segment && FALSE == shm->created) {
if(NULL != shm->descriptor){
ret = UnmapViewOfFile(shm->descriptor) ? 0 : -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think that we need to UnmapViewOfFile() "unconditionally". From https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga:

Therefore, to fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling UnmapViewOfFile and close the file mapping object handle by calling CloseHandle.

If we only unmap when the number of attachments drops to zero, that would not necessarily match the attachments.

}
shm->descriptor = NULL;
CloseHandle(shm->segment);
shm->segment = INVALID_HANDLE_VALUE;
shm->addr = NULL;
}
}

return ret;
}/*}}}*/

Expand Down
2 changes: 2 additions & 0 deletions TSRM/tsrm_win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ typedef struct {
typedef struct {
void *addr;
HANDLE segment;
BOOL created;
int shm_nattch;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I see that we need to track the number of attachments for each process/thread, so that we're able to close the file handle per process/thread when we're done with the SHM.

struct shmid_ds *descriptor;
} shm_pair;

Expand Down
Loading