I've seen many examples of ReportEvent function on the web. In those examples, the handle that is sent to ReportEvent (first argument) is created right before the call to ReportEvent and destroyed right after the call (with RegisterEventSource and DeregisterEventSource respectively).
Is there a reason why the HANDLE is alive only for a short time? Why would it be better than just creating the HANDLE in the begining of the porgram and destroying it at the end? (after all it's only one HANDLE and around 16 million is the maximum). Is there no overhead on creating and destroying the HANDLE each time we call ReportEvent?
Thanks in advance,
Dror
Yes you can. At the beginning of wmain, you may do:
HEVENT hEventLog = RegisterEventSource(NULL, PROVIDER_NAME);
And, at the end, of wmain,
if (hEventLog)
DeregisterEventSource(hEventLog);
This should do, and you may reuse same handle
The more interesting aspect of this question is following - can we call RegisterEventSource only and then assume that exiting process is enough to auto-close all related handles including the one which was obtained via RegisterEventSource?
In other words - if we know for sure that process will be exited sometime then we can call RegisterEventSource only. Nothing more.
And even more clarifying form of the same question - if we will not call DeregisterEventSource() what problems that may cause? Would be there a kind of internal leak in whole OS? Or any other consequences?
For example:
I need to call ReportEvent() in lot of different DLLs, as result - in every DLL I always have to call 3 functions: RegisterEventSource, ReportEvent, DeregisterEventSource. I would like to use internal static variable with a handle, call RegisterEventSource only once and then never call DeregisterEventSource with a hope that when process exited all related handles will be auto-closed.
Would that work?
Related
Let's say I have an array of non-blocking MPI requests initiated in a series of calls to MPI_ISEND (or MPI_IRECV). I store the request info in the array xfer_rqst. It is my understanding that when a request completes, its corresponding value in xfer_rqst will be set to MPI_REQUEST_NULL. Further, it's my understanding that if a call is made to MPI_WAITALL, it will have work to do only if some requests in xfer_rqst still have some value other than MPI_REQUEST_NULL. If I have it right, then, if all requests complete before we get to the MPI_WAITALL call, then MPI_WAITALL will be a no-op for all intents and purposes. If I am right about all this (hoo boy), then the following Fortran code should work and maybe occasionally save a useless function call:
IF (ANY(xfer_rqst /= MPI_REQUEST_NULL)) &
CALL MPI_WAITALL(num_xfers, xfer_rqst, xfer_stat, ierr)
I have actually run this several times without an issue. But still I wonder, is this code proper and safe?
It is indeed often the case that you can decide from the structure of your code that certain requests are satisfied. So you think you can skip the wait call.
And indeed you often can in the sense that your code will work. The only thing you're missing is that the wait call deallocates your request object. In other words, by skipping the wait call you have created a memory leak. If your wait call is in a region that gets iterated many times, this is a problem. (As noted in the comments, the standard actually states that the wait call is needed to guarantee completion.)
In your particular case, I think you're wrong about the null request: it's the wait call that sets the request to null. Try it: see if any requests are null before the wait call.
I am finding DuplicateHandle() very confusing. The third and fourth params, hTargetProcessHandle and lpTargetHandle seem to imply that this API function does some form of interprocess communication, but what I have been reading online seems to imply (without saying directly) that in fact this function cannot communicate with anything outside of the address space of its own process and that if you really do want to say copy the local process handle to another process you have to do that yourself manually.
So can someone please please take pity on me and tell me definitively whether or not this function does any IPC itself? Also if it doesn't do any IPC then what is the point of those two parameters? How can there be a 'target' if no data is sent and the output of this function is not visible to other processes?
At first I thought I could call GetCurrentProcess() and then use DuplicateHandle() to copy the local process handle to another process, but then I started to realize that it probably isn't that easy.
The third parameter hTargetProcessHandle is documented as
A handle to the process that is to receive the duplicated handle.
That means that the handle (which is just a numeric value underneath) will become usable within the target process. However, how you get this handle into the target process and in what context it is to be used there is out of the scope of that function. Also note that "is to receive" points in the future and it refers to the result of the call, so it must be after the call has finished.
As an analogy, you want to allow a friend in your house. For that, you are creating a second key to your door. Just that doesn't mean that your friend can now unlock your door, because you first have to give it to them, but it's a first step.
When I compile with the configuration set to release (for both x86 and x64), my program fails to complete. To clarify, there are no build errors or execution errors.
After looking for a cause and solution for the issue, I found Program only crashes as release build -- how to debug? which proposes that it is an array issue. Though this solve my problem, it gave me some insight on the matter (which I leave here for the next person).
To further muddle matters, it's only when a subroutine on the main thread has an execution time greater than about 0ms.
Here are the relevant sections of code:
// Startup Progress Bar Thread
nPC_Current = 0; // global int
nPC_Max = nPC; // global int (max value nPC_Current will reach)
DWORD myThreadID;
HANDLE progressBarHandle = CreateThread(0, 0, printProgress, &nPC_Current, 0, &myThreadID);
/* Do stuff and time how long it takes (this is what increments nPC_Current) */
// Wait for Progress Bar Thread to Terminate
WaitForSingleObject(progressBarHandle, INFINITE);
Where the offending line that my program gets stuck on is that last statement, where the program waits for the created thread to terminate:
WaitForSingleObject(progressBarHandle, INFINITE);
And here is the code for the progress bar function:
DWORD WINAPI printProgress(LPVOID lpParameter)
{
int lastProgressPercent = -1; // Only reprint bar when there is a change to display.
// Core Progress Bar Loop
while (nPC_Current <= nPC_Max)
{
// Do stuff to print a text progress bar
}
return 0;
}
Where the 'Core' while loop generally won't get a single iteration if the execution time of the measured subroutine is about 0ms. To clarify this, if the execution time of the timed subroutine is about 0ms, the nPC_Current will be greater than nPC_Max before the printProgressBar executes once. This means that thread will terminate before the main thread begins to wait for it.
If anyone would help with this, or provide some further insight on the matter, that would be fantastic as I'm having quite some trouble figuring this out.
Thanks!
edits:
wording
deleted distracting contents and added clarifications
My guess would be that you forgot to declare your shared global variables volatile (nPC_Current specifically). Since the thread function itself never modifies nPC_Current, in the release version of the code the compiler optimized you progress bar loop into an infinite loop with never changing value of nPC_Current.
This is why your progress bar never updates from 0% value in release version of the code and this is why your progress bar thread never terminates.
P.S. Also, it appears that you originally intended to pass your nPC_Current counter to the thread function as a thread parameter (judging by your CreateThread call). However, in the thread function you ignore the parameter and access nPC_Current directly as a global variable. It might be a better idea to stick to the original idea of passing and accessing it as a thread parameter.
The number one rule in writing software is:
Leave nothing to chance; check for every single possible error, everywhere.
Note: this is the number one rule not when troubleshooting software; when there is trouble, it is already too late; this is the number one rule when writing software, that is, before there is even a need to troubleshoot.
There is a number of problems with your code; I cannot tell for sure that any one of those is what is causing you the problem that you are experiencing, but I would be willing to bet that if you fixed those, and if you developed the mentality of fixing problems like those, then you would not have the problem you are experiencing.
The documentation for WaitForSingleObject says: "If this handle is closed while the wait is still pending, the function's behavior is undefined." However, you do not appear to be asserting that CreateThread() returned a valid handle. You are not even showing us where and how you are closing that handle. (And when you do close the handle, do you assert that CloseHandle() did not fail?)
Not only you are using global variables, (which are something that I would strongly advice against,) but also, you happily make a multitude of assumptions about their values, without ever asserting any one of those assumptions.
What guarantees do you have that nPC_Current is in fact less than nPC_Max at the beginning of your function?
What guarantees do you have that nPC_Current keeps incrementing over time?
What guarantees do you have that the calculation of lastProgressPercent does not in fact keep yielding -1 during your loop?
What guarantees do you have that nPC_Max is not zero? (Division by zero on a separate thread is kind of hard to catch.)
What guarantees do you have that nPC_Max does not get also modified while your thread is running?
What guarantees do you have that nPC_Current gets incremented atomically? (I hope you understand that if it does not get incremented atomically, then at the moment that you read it from another thread, you may read garbage.)
You have tagged this question with [C++], and I do see a few C++ features being used, but I do not really see any object-oriented programming. The thread function accepts an LPVOID parameter precisely so that you can pass an object to it and thus continue being object-oriented in your second thread, with all the benefits that this entails, like for example encapsulation. I would suggest that you use it.
You can use (with some limitations) breakpoints in release...
Does this part of the code:
/* Do stuff and time how long it takes (this is what increments nPC_Current) */
depend on what printProgress thread does? (If so, you have to assure time dependence, and order conveniently) Are you sure this is always incrementing nPC_Current? Is it a time dependent algorithm?
Have you tested the effect that a Sleep() has here?
I have a class Class in which there's a member property HANDLE handle to a thread (We can assume it is set to NULL at that point) . at some point , a method within Class dispatches one of it's own methods Class::threaded() (using another function that is external to the class itself, but it doesn't really matter here) with CreateThread(). The calling thread will then may continue to other function outside of Class.
As CloseHandle() must be called for the HANDLE returned from CreateThread() , I was wondering if calling it from Class::threaded() just before it returns would be a decent solution.
Two basic ways to deal with a thread. Commonly you're interested when the thread terminates, you'll need to keep the handle around so you can find out. And of course you'll close it after you detected termination. Or you don't care, fire-and-forget style, or have additional synchronization objects to signal that the thread function completed and/or you ask it to exit. In which case you simply close the handle as soon as you start it.
Do keep in mind that it is not necessary to keep the handle opened to keep the thread running, in case that's the source of the confusion.
You receive a handle to the thread so you can manage it. If there is no need to it, you can call CloseHandle right away.
Closing the HANDLE will have no terminate the thread, so, it's secure to close it if nothing from the thread is of interest to you.
You can close it as soon as you are through using it. Closing it has no effect on the thread. (The handle is reference counted by OS.)
I'm writing a VC++ application. Just for the sake of argument, what could cause the ResetEvent API to fail? The Microsoft documentation is not clear on this. Thanks.
Most commonly an invalid handle will cause this to fail. An invalid handle, in turn, could result from:
the handle being closed by another process or thread prematurely
passing gobbledy-gook to ResetEvent()
Passing a handle to a thing that isn't an even
Number 1 can often be avoided by creating a duplicate of the handle, by calling DuplicateHandle().
GetLastError() generally will tell you exactly what the problem is, or at least point you in the direction.
Without access to the source of Windows we can only guess. Here's my guess at what could go wrong:
The handle is not a valid handle to an event object.
The handle does not have the necessary access rights. The documentation states that the handle must have the EVENT_MODIFY_STATE access right.
The OS runs out of memory or has some other critical failure.
Reading the WINE source reveals no other explicit failure modes.