4

Background: I am trying to create a memory mapped file that can be accessed by multiple processes. In the below code I only put in the code that pertains to the question I currently have to make things simpler. According to msdn I should be able to create a filemap, map the view of the file and close the handle I received from CreateFileMapping and the MapViewOfFile will keep my FileMap alive. The FileMap should be still accessible until I UnmapViewOfFile.

MSDN: CreateFileMapping function

Mapped views of a file mapping object maintain internal references to the object, and a file mapping object does not close until all references to it are released. 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. These functions can be called in any order.

Problem: After successfully mapping the view of the file and then closing the handle received by CreateFileMapping the FileMap no longer exists (it should still exist) and my MemMapFileReader is able to create a new map with error of 0. (When it should be receiving error 183 'already exists')

Bad Solution: Not closing the handle allows it to be accessed by the MemMapFileReader program but causes a handle leak in the MemMapFileCreator because the handle is never closed until the process is closed.

Question: What am I missing or doing wrong?

MemMapFileCreator

#include "stdafx.h" #include <windows.h> #include <stdio.h> #include <conio.h> #include <tchar.h> #include <iostream> #define BUF_SIZE 256 TCHAR szName[] = TEXT("MyFileMappingObject"); TCHAR szMsg[] = TEXT("Message from first process."); int _tmain() { HANDLE hMapFile; LPCTSTR pBuf; hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // use paging file NULL, // default security PAGE_READWRITE, // read/write access 0, // maximum object size (high-order DWORD) BUF_SIZE, // maximum object size (low-order DWORD) szName); // name of mapping object DWORD lastError = GetLastError(); if (hMapFile == NULL) { _tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError()); std::cin.get(); return 1; } pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object FILE_MAP_ALL_ACCESS, // read/write permission 0, 0, BUF_SIZE); if (pBuf == NULL) { _tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError()); CloseHandle(hMapFile); std::cin.get(); return 1; } CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR))); CloseHandle(hMapFile); _getch(); UnmapViewOfFile(pBuf); return 0; } 

MemMapFileReader

#include "stdafx.h" #include <windows.h> #include <stdio.h> #include <conio.h> #include <tchar.h> #include <iostream> #pragma comment(lib, "user32.lib") #define BUF_SIZE 256 TCHAR szName[] = TEXT("MyFileMappingObject"); int _tmain() { HANDLE hMapFile; LPCTSTR pBuf; hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, // read/write access 0, BUF_SIZE, szName); // name of mapping object DWORD lastError = GetLastError(); if (hMapFile == NULL) { _tprintf(TEXT("Could not open file mapping object (%d).\n"), GetLastError()); std::cin.get(); return 1; } pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object FILE_MAP_ALL_ACCESS, // read/write permission 0, 0, BUF_SIZE); if (pBuf == NULL) { _tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError()); CloseHandle(hMapFile); std::cin.get(); return 1; } MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK); UnmapViewOfFile(pBuf); CloseHandle(hMapFile); std::cin.get(); return 0; } 
2
  • Could you quote, or link to, the MSDN section you're referring to? Commented Apr 9, 2015 at 15:26
  • "then closing the handle received by CreateFileMapping the FileMap no longer exists (it should still exist)" - it still exist. but it name is destroyed. after close handle - your intially named section become unnamed. as result you cannot open it by name. but section still exist and full function Commented Apr 10, 2015 at 7:35

5 Answers 5

5

From MSDN:

Mapped views of a file mapping object maintain internal references to the object, and a file mapping object does not close until all references to it are released. 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. These functions can be called in any order.

The CreateFileMapping documentation says that to fully close a file all handles must be closed and the order does not matter. This logic is not invertible: you cannot close a handle and expect to use the other handles as if the file mapping wasn't 'closed'.

In other words, it means that to clean up the file mapping you need to close all handles in any order. However, you can not close the underlying file-mapping object and still use the views that depend on it.

Sign up to request clarification or add additional context in comments.

6 Comments

Then I guess I can assume that Compact 2013 runs differently? In Compact 2013 the file-mapping object remains accessible even after closing its handle (if its view has been mapped) until unmapviewoffile is called
Implementation details can of course vary, but from the documentation you can not rely on this behaviour.
Good Point. It also doesn't hurt to hold on to the handle if it is closed in the destructor.
you do not understand root of problem - the disappearance of the name of the object. everything that you have written is irrelevant
@sutol: not at all. The name disappears precisely because there are no more handles to the object.
|
2

The CreateFileMapping() documentation says:

Mapped views of a file mapping object maintain internal references to the object, and a file mapping object does not close until all references to it are released.

The CloseHandle() documentation says:

In general, CloseHandle invalidates the specified object handle, decrements the object's handle count, and performs object retention checks. After the last handle to an object is closed, the object is removed from the system.

The mapped views simply keep the mapping object's reference count above zero until they are unmapped, but they do not keep the underlying file/mapping itself open.

2 Comments

you do not understand root of problem - the disappearance of the name of the object. everything that you have written is irrelevant
I understand perfectly, and what I posted is relevant. "CloseHandle invalidates the specified object handle" means the mapping object is GONE when CloseHandle() is called. The fact that the views are still mapped does not prevent the mapping object and its name from disappearing. You can use a tool like SysInternals Process Explorer to verify that.
0

after you close Section handle view in creator process not disappear, until unmaping bat it name - "MyFileMappingObject" in NT namespace is destroyed. as result next call to CreateFileMapping - not found named object "MyFileMappingObject" and create new (when mast by your logic open existing). again - section not destroyed, but it name is destroyed. what you name - Bad Solution - really not bad - this is absolute normal - you mast not close handle to Section. and this is not handle leak - simply will be permanent open handle in your process. this situation is absolute normal

you use is NAMED section. after close it handle - section NOT DESTROYED - because exist also view of section, which hold it. but NAME of section is DESTROYED. and new call to create section - not open existing but create new.

3 Comments

True, as long as I close the handle later it should be fine.
simply not close section handle. this all what need
@Remy Lebeau: you are nothing understand. absolutely."means the mapping object is GONE when CloseHandle() is called." - delirium. section (mapping object) is not GONE when CloseHandle() is called. it NAME onlt is gone.
0

exist else one solution, which show that you all wrong. it require SE_CREATE_PERMANENT_PRIVILEGE, but for demo this is normal

STATIC_OBJECT_ATTRIBUTES_EX(g_oa, "\\BaseNamedObjects\\MyFileMappingObject", OBJ_CASE_INSENSITIVE|OBJ_PERMANENT, 0, 0); NTSTATUS CreateAndWrite() { NTSTATUS status; HANDLE hSection; LARGE_INTEGER Size = { PAGE_SIZE }; if (0 <= (status = ZwCreateSection(&hSection, SECTION_MAP_READ|SECTION_MAP_WRITE, &g_oa, &Size, PAGE_READWRITE, SEC_COMMIT, 0))) { PVOID BaseAddress = 0; SIZE_T ViewSize = 0; if (0 <= (status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READWRITE))) { STATIC_WSTRING(szMsg, "Message from first process."); memcpy(BaseAddress, szMsg, sizeof(szMsg)); ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); } ZwClose(hSection); } return status; } NTSTATUS OpenReadAndDestroy() { NTSTATUS status; HANDLE hSection; if (0 <= (status = ZwOpenSection(&hSection, SECTION_MAP_READ|DELETE, &g_oa))) { PVOID BaseAddress = 0; SIZE_T ViewSize = 0; if (0 <= (status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY))) { MessageBox(0, (PCWSTR)BaseAddress, 0, 0); ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); } ZwMakeTemporaryObject(hSection); ZwClose(hSection); } return status; } if (0 <= GotPermanentPrivilege()) { if (0 <= CreateAndWrite()) { // at this point - no one handles for "MyFileMappingObject" exist // we close all and even unmap view // but 1 reference to section object exist (by OBJ_PERMANENT flag) // and NAME is still exist // as result we can open,map and read data :) OpenReadAndDestroy(); } } 

what you say for this ? section is destroyed, after all handle closed ?? cannot use views ? D)

p.s. SE_CREATE_PERMANENT_PRIVILEGE - usually have only LocalSystem, but we can got it, if have SE_DEBUG_PRIVILEGE+SE_IMPERSONATE_PRIVILEGE - open "system" thread and impersonate on it

Comments

0

Looking at your description, it seems that you want your Creator app to close before/irrespective of any client. This will have following things: As soon as your creator app closes, Windows will automatically close any Handles opened by that process because this is a resource leak prevention mechanism. This means, if no client is attached to the just created file mapping object creator is the only app referring it. When this app closes, all the handles referring the file mapping object are closed which in turn will trigger Windows rule that "When all the handles to a File Mapping Object are closed the object will be automatically freed" causing your object to be removed!! This is the reason your client apps get error 0.

Approach 1:

Motivation to this approach: You want to write one application and multiple instances of same app will communicate via shared memory.

In such apps involving shared memory for inter-process communication, the only difference between the two apps that we develop boils down to just "who creates the object", rest of the operations are to use the shared memory and are same for both the apps. So we can avoid developing two apps and instead write only one.

Another motivation for this approach is that, in client-server LIKE architecture it is mandatory that server starts before client. If you do not want to have this restriction then this approach will help. CAUTION, this means you need to think of changing the architecture and this can be quiet a task for existing apps!

Implementation:

// CreateFileMapping object ... // Check the error value using GetLastError. If (GetLastError() == ERROR_ALREADY_EXISTS) { // I am a client } else { // I am creator/server } 

In your case, as you are allowing your creator app to close before clients means the creator does not assume much big responsibility like a server. If that is the case then you can use above approach. It might save you of maintaining one more APP!

Approcah 2: Keep your app alive untill at least any one client connects. But again this will be a little bit difficult to implement!

Regarding UnmapViewOfFile This function is a proper way to close/release the system resources. BUT this does not mean that, closing an app without calling it will keep your resources ALIVE ! Not calling it means two cases:

  1. Application crashed.
  2. Developer forgot to call it!

This will cause resource leaks! Windows fault tolerance mechanism mitigates this issue by closing all the handles opened by a process when it ends either properly or abruptly. SO we can think of UnmapViewOfFile as a function to PROPERLY release resources.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.