> SteveKing wrote:
>> 1. critical sections aren't good enough to guard the cache. The reason
>> for that is that the cache is global in the COM dll and therefore used
>> by all processes concurrently. A mutex is needed to guard it.
>> You can easily try this out yourself: create a simple dll which only
>> shows a messagebox telling you the address of a dll global string.
>> Then create a simple exe which does nothing more than load this dll
>> (make sure it doesn't exit immediately so the dll stays loaded). Then
>> start the exe several times - each time you start the exe another
>> process is started and the dll is loaded into process space. But the
>> dll tells you the same address of the global string, no matter which
>> process it has been loaded from.
>> Since I've experienced crashs when just using critical sections I
>> started to wonder and used mutexes for some time now. But to be sure I
>> just wrote such a test dll and exe.
> Hmmm - I've extended the test a little. Now it seems that the dll has
> different global variables for each process as I would expect. I'll do
> some more tests and report back...
(It seems like it has been resolved that the data isn't actually
shared across processes, but all the same, this seemed relevant.
If everyone already knows this like the back of their hand,
CRITICAL_SECTIONs can not be shared across processes; if you
have data that needs to be synchronized across processes
To use a mutex, you must either:
a. give the mutex a name so that all processes access the
b. call DuplicateHandle()
Just sharing the handle value for the mutex created in one
process with another is not sufficient as HANDLEs are a
per process data structure.
So, for example, this works:
HANDLE hMutex = ::CreateMutex(0, TRUE, _T("TSVN_Cache_mutex"))
if ( hMutex && ::GetLastError() != ERROR_ALREADY_EXISTS )
// I created at and currently own it, now would
// be a good time to initialize any data structures
// that need initializing...
This code executing in multiple processes will use the
same MUTEX and syncrhonize the processes together.
But, this does not work:
bool g_bCsInitialized = false;
HANDLE g_hMutex = 0;
#pragma comment(linker, "/SECTION:.MYSEC,RWS")
if ( g_hMutex == 0 )
g_hMutex = ::CreateMutex(0, TRUE, 0)
if ( ! g_bCsInitialilzed )
g_bCsInitialized = true;
In this case, both g_hMutex and g_cs are shared between
all processes mapping the object.
However, because handles are per-process objects,
only the process that actually called ::CreateMutex()
really has a valid handle to the mutex.
In fact, handle value x in process 'a' will be the
mutex, but handle value x in process 'b' may
be invalid or refer to some completely different
object, like a file. In that case WaitForSingleObject()
could work anyway, but you wouldn't really own the
mutex when it returned... an I/O just completed
on your file object though!
The CRITICAL_SECTION is can't be shared for a similar reason;
embedded in the CRITICAL_SECTION is a HANDLE. The
first time the CRITICAL_SECTION can't be immediately
acquired, a EVENT / SEMAPHORE is created and the
HANDLE is stored w/i the criticial seciton. All
subsequent waits for the CRITICAL_SECTION use this
handle, which is only valid in the context of the
process that created it.
The long and short of it-- don't put handles or
critical sections in shared data sections or
shared memory. It just won't work right.
To unsubscribe, e-mail: email@example.com
For additional commands, e-mail: firstname.lastname@example.org
Received on Thu Jan 6 21:43:27 2005