DylSmith DylSmith - 3 months ago 14
C Question

Use Windows Semaphores to synchronize Windows File Mappings

I want to use Windows Semaphores to add synchronization to a Windows File Mapping. So, one process creates the file mapping and another (perhaps multiple other processes) can come in and access the data that is shared. Can anyone give a suggestion as to how this can be done. I have done the following:

In the process that creates the file mapping, I have used

CreateSemaphore
and specified a name. In another process that attempts to access the data, I use
OpenSemaphore
to get a handle to the created sempahore, then I call
WaitForSingleObject
, I then switch on this value, and if its
WAIT_OBJECT0
, I perform the work, and finally calling
ReleaseSemaphore
once the work is done.
I am doing this in C, using a JNI shared library.

The problem is that it simply goes into the default case. Is there anything else that I should do, or am I missing something?

I'm pretty new to how Windows sems work, and I cannot find a concrete example
of how they work between multiple processes (no threads). If anyone can give any suggestions, It would be much appreciated.

Here is some code:

Create the file mapping

// create the semaphore here
semaphore = CreateSemaphore(
NULL,
10,
10,
SEMAPHORE_NAME
);

// some semaphore error checking
if (semaphore == NULL) {
printf("Error occured creating semaphore %d\n", GetLastError());
return -1;
}

//create mapping object
mappedFileHandle = CreateFileMapping (
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
BUFFER_SIZE,
MEMORY_MAPPING_NAME
);

if (mappedFileHandle == NULL) {
printf("Error creating a mapped file: %d", GetLastError());
return -1;
}

// map view of a file into address space of a calling process
buffer = (LPCTSTR) MapViewOfFile (
mappedFileHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
BUFFER_SIZE
);

if (buffer == NULL) {
printf("Could not map view");
CloseHandle(mappedFileHandle);
return -1;
}

CopyMemory(buffer, str, (_tcslen(str) * sizeof(TCHAR))); // problem!!
UnmapViewOfFile(buffer);
CloseHandle(mappedFileHandle);
// CloseHandle(semaphore);


Process code that gets the data

// try open the semahore
semaphore = OpenSemaphore (
SEMAPHORE_ALL_ACCESS,
NULL,
SEMAPHORE_NAME
);

// some error checking
if (semaphore == NULL) {
printf("Could not open semaphore %d\n", GetLastError());
return -1;
}

waitResult = WaitForSingleObject(
semaphore,
-1 // block
);

// try to open the file mapping -- SHOULD BE DONE ATOMICALLY
// ======================================================================

switch (waitResult) {
case WAIT_OBJECT_0:
printf("Got in wait_result0");
mappedFileHandle = OpenFileMapping (
FILE_MAP_ALL_ACCESS,
FALSE,
MEMORY_MAPPING_NAME
);

if (mappedFileHandle == NULL) {
printf("Could not open file mapping");
return errorForJavaProgram;
}

// read data here, must be a critical region

buffer = (LPTSTR) MapViewOfFile(
mappedFileHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
BUFFER_SIZE
);

if (buffer == NULL) {
printf("Could not map view");
CloseHandle(mappedFileHandle);
return errorForJavaProgram;
}

message = (*env)->NewStringUTF(env, buffer);

if (!ReleaseSemaphore(semaphore, 1, NULL)) {
printf("An error occured releasing the semaphore: %d\n", GetLastError());
return -1;
}
default:
printf("Got to default \n");
} //switch

Answer

Your switch statement is subject to fall through. For one of the many discussions that can be found here on Stack Overflow, see Does case-switch work like this?.

Your code executes the WAIT_OBJECT_0 and then simply continues to the default case. You need to add a break or a return at the very end of the WAIT_OBJECT_0 case.