Re: ::EnterCriticalSection locking.
Quote:
Originally Posted by googler
Yes, it compiles. But try doing "dumpbin /headers" on your exe file. In the "OPTIONAL HEADER VALUES" area, right below "number of directories" see if you have an RVA for "Load Configuration Directory". There should be an RVA there to the copy of the struct body (which should be in the .rdata section).
You're right about that, I tested using MapAndLoad(...)/GetImageConfigInformtion(...) and it also claims that the file does not contain any load configuration.
Quote:
Originally Posted by googler
If this pointer is not set, the system won't recognize it.
Well, thats the strange thing. My critical sections as still timing out after the specified milliseconds.
This needs further investigation...
- petter
Re: ::EnterCriticalSection locking.
I tried it again. Yesterday, I wrote it like this:
Code:
#ifdef __cplusplus
extern "C" {
#endif
const IMAGE_LOAD_CONFIG_DIRECTORY32 _load_config_used = {
/* blah blah */
};
#ifdef __cplusplus
}
#endif
And this wasn't getting a load configuration set when compiled as CPP. The critical sections weren't timing out either.
Today, I tried it the other way...
Code:
extern "C" const IMAGE_LOAD_CONFIG_DIRECTORY32 _load_config_used = {
/* blah blah */
};
and guess what? dumpbin shows there is a load configuration, and the critical sections are timing out.
So I checked the help for extern "C" and I noticed that it talks about declarations. So it seems that if you just have a definition inside an extern "C" {} block, they don't get extern "C"ed !!!! But if you write a definition with its own private extern "C", it does get extern "C"ed. Talk about strange...
So, I guess the following version should work whether compiling as C or C++:
Code:
#ifdef __cplusplus
extern "C"
#endif
const IMAGE_LOAD_CONFIG_DIRECTORY32 _load_config_used = {
/* blah blah */
};
Re: ::EnterCriticalSection locking.
Vaderman, before modifying the default cs timeout, I would suggest adding some trace debug statements so that you can pinpoint which objects are getting locked and/or if making sure you don't have any circular dependencies.
You mention previous owners of the code say that this code worked fine before. My first reaction to that is 'R i ght.' However, if it did work fine before, can you determine what changed in the code that might cause it to fail? If nothing has changed in the code, then don't assume it ever worked correctly (it might just be that this flaw wasn't uncovered before or something else changed in the system like different hardware or increased load).
As far as locking up... Are you sure you are always calling .Unlock(). Are there any code paths that prevent Unlock from always getting called? Note: if you kill a thread that shares the critical section, this will prevent the thread from calling .Unlock. Could this be occuring?
Someone else mentioned thread starvation. How many threads are accessing the cs? If there are many threads, you may consider using a thread pool mechanism to restrict the number of threads (use the QueueUserWorkItem api or the queuing approach mentioned earlier).
I would suggest going over your code carefully. Here are a few things to look for:
- Make sure that you aren't killing any threads that share a lock object..
- Make sure that .Unlock ALWAYS gets called.
- Next, I would look at how long you are holding onto the lock. Are you locking, accessing the resource, and then immediately unlocking? Or are you locking, accessing the resource, performing some other lengthy work, then unlocking the resource?
- If so, ask yourself if this work needs to be done while the resource is locked or if you can perform the work after the resource has been unlocked. Sometimes, the lock is held too long because of a coding oversite. Other times, you need to hold on to the lock because the resource is being updated during the work operation. In the latter case, you can often reduce contention by making a copy of the resource that the long operation uses. You would lock, copy, unlock and perform the lengthy operation; then you would lock, update the original from the copy, and unlock. At first it might seem like doubling the amount of locking per work operation isn't ideal, but two short locks are better than one long lock.
- If most of the time you are reading (with very few writes), consider moving to a singlewriter/multiple reader locking object rather than a critical section (where every lock is treated as a write lock).
Arjay