I/O completion ports closing a handle cause reads to complete - winapi

I have iocp running and working (mostly) -- but should calling CloseHandle() on a handle cause it to complete?
e.g., I've called ReadFile() and it's now waiting for input to read. At another point I'm calling CloseHandle() from another thread in the pool used to service iocp completion packets. I expect for there to be a completion on the previous ReadFile() call with an ERROR_INVALID_HANDLE, but I'm not seeing that. Instead, it never seems to return. Could this be a sign that something else is holding a reference to the handle? If so, how would you suggest figuring that out/debugging it?
Any suggestions?
Thanks!

Related

Closehandle() not terminating the process

The process is not getting terminated after closing its handle in CloseHandle().
Well I have a process created by CreateProcess() api. Even after closing Its handle it is still running.
From the msdn, they say that CloseHandle() closes the handle and doesn't terminate process. Have to call terminate thread for that. Then why CloseHandle()?
But when I checked CloseHandle()'s return value, it succeeded. If so I want know what is actually done in this CloseHandle() and why it returns successfully. And I want to know what all operation can be done on the process using its handle. I felt misleading, as CloseHandle() succeeds but the process still runs on!
Would also be great what actually contains in the handle of a process and is there any differences with other type of handles? (file,I/O etc)
Why does closing the handle not terminate the process? Have to call TerminateProcess for that.
Closing the handle does not terminate the process because it would be absurd. Processes generally run independently of each other. If closing the process handle terminated the corresponding process, this wouldn't be the case since when a program exits, all open handles it holds are closed. Which would for example mean that if Explorer crashed, every program you started would be instantly terminated. That would be a desaster, and thus closing the process handle does, by design, not terminate the program.
Terminating a process is almost always a very bad idea. The same goes for terminating a thread. Never do that if you can avoid it. If you want a thread/process to exit, send it a message and wait until it has exited (on its own behalf). This guarantees that data is properly saved and in a consistent state, no resources are leaked, and that no serious conflicts can occur (such as a thread being terminated while it holds a lock).
Terminating threads is often troublesome, and sometimes catastrophic. The same goes for terminating processes. It is only "allowable" to terminate a process or a thread when it is caught in an infinite loop and non-responsive.
Then why do you have to close the handle anyway, and why are you getting one at all if you must close it?
You can do certain things with a handle, among these are for example ReadProcessMemory, WriteProcessMemory, CancelIoEx, running a debugger, use PSAPI, and a few others. Also you can wait on the handle, it will be signalled when the process exits. That is a very simple way of inter-process synchronization.
On the other hand, the operating system cannot release resources as long as you hold the handle open and thus have a "legitimate right" to access these. How can you for example wait for a process, if the process (or at least its structures) does not exist at all any more?
This (and the fact that the handle itself is a resource) is why you should close the handle as soon as possible if you don't need it. Holding it indefinitely requires the OS to keep resources around that are not needed but cannot be freed.
Closing the handle tells the operating system that you don't need it any more, so whenever the OS wants to release all resources associated with the process, it can do so.
What is contained in the process handle?
Like all handles, the process handle is merely an opaque integer that doesn't contain anything. It is an index in a kernel-owned table, technically a void*, but that is only an implementation detail. The actual kernel structure that it refers to is not something you can directly access, not in an easy way anyway.
A handle is a reference to some kernel-managed, reference-counted object. Normally, closing the last handle to an object will result in the destruction of such an object.
But: processes and threads are not killed when closing the last handle, you can think that they "start living on their own" after being started. Without this exception, you couldn't have a process outlive its parent, since each process' handles is closed automatically at process termination (and having a thread outlive its parent would require needless complications).
Anyway, all of this is documented: if you read the documentation of CloseHandle you would have found:
Closing a thread handle does not terminate the associated thread or
remove the thread object. Closing a process handle does not terminate
the associated process or remove the process object. To remove a
thread object, you must terminate the thread, then close all handles
to the thread. For more information, see Terminating a Thread. To
remove a process object, you must terminate the process, then close
all handles to the process. For more information, see Terminating a
Process.
What you described is behavior by design. A process runs on its own, it might have zero or more handles opened, which let their holders control the process in certain ways. Once you hold a handle, you are responsible for closing it.
Termination of the process is a different thing, and you basically are not expected to terminate externally: you never know where exactly you stop the process. You are expected to somehow signal that you want the process termination, so that the process could figure it out and terminate its activity internally, and gracefully.

WaitForSingleObject() vs RegisterWaitForSingleObject()?

What is the advantage/disadvantage over using RegisterWaitForSingleObject() instead of WaitForSingleObject()?
The reason that I know:
RegisterWaitForSingleObject() uses the thread pool already available in OS
In case of the use of WaitForSingleObject(), an own thread should be polling for the event.
the only difference is Polling vs. Automatic Event? or Is there any considerable performance advantage between these?
It's pretty straight-forward, WaitForSingleObject() blocks a thread. It is consuming a megabyte of virtual memory and not doing anything useful with it while it is blocked. It won't wake up and resume doing useful stuff until the handle is signaled.
RegisterWaitForSingleObject() does not block a thread. The thread can continue doing useful work. When the handle is signaled, Windows grabs a thread-pool thread to run the code you specified as the callback. The same code you would have programmed after a WFSO call. There is still a thread involved with getting that callback to run, the wait thread, but it can handle many RWFSO requests.
So the big advantage is that your program can use a lot less threads while still handling many service requests. A disadvantage is that it can take a bit longer for the completion code to start running. And it is harder to program correctly since that code runs on another thread. Also note that you don't need RWFSO when you already use overlapped I/O.
They serve two different code models. In case with RegisterWaitForSingleObject you'll get an asynchronous notification callback on a random thread from the thread pool managed by the OS. If you can structure your code like this, it might be more efficient. On the other hand, WaitForSingleObject is a synchronous wait call blocking (an thus 'occupying') the calling thread. In most cases, such code is easier to write and would probably be less error-prone to various dead-lock and race conditions.

How to interrupt select call on windows?

I know it's probably a basic question, but I'd like to hear the best way to realize it.
So to the problem. I have a driver thread using a call to select, and I have a GUI thread that needs sometimes to interrupt select by writing to some file descriptor within the same process (GUI FD or something). I used pipe in UNIX, but I'm not experienced in sockets for Windows, so I'm not sure what kind of FD I should use. Example is greatly appreciated but not required ).
Thanks.
select() is not the best to implement asynchronous I/O under Windows. unfortunately, the select() call on windows only works with socket handles and not with pipe or fie handles.
you should have a look at overlapped I/O.
by using an event in your overlapped structure, you can have a behaviour close to select(). any event on a socket will trigger an event, which you can wait on by using WaitForMultipleObjects(). now, your GUI thread can signal the I/O thread by setting a specific (separate) event, which you create using the CreateEvent() call.
You could set the timeout shorter on the select and then loop round if it was a timeout. Or you could send a simple packet to the socket being selected causing it to wake up.

How to find out when CancelIo() is done?

CancelIo() is supposed to cancel all pending I/O operations associated with the calling thread. In my experience, CancelIo() sometimes cancels future I/O operations as well. Given:
ReadFile(port, buffer, length, &bytesTransferred, overlapped);
If I invoke CancelIo(port) immediately before the read, GetQueuedCompletionStatus() will block forever, never receiving the read operation.
If I invoke CancelIo(port) immediately after the read, GetQueuedCompletionStatus() will return 0 with GetLastError()==ERROR_OPERATION_ABORTED
If I invoke CancelIo(port) and there are no pending or subsequent reads, GetQueuedCompletionStatus() will block forever.
The key point here is that there is no way to detect when CancelIo() has finished executing. How can I ensure that CancelIo() is done executing and it is safe to issue further read requests?
PS: Looking at http://osdir.com/ml/lib.boost.asio.user/2008-02/msg00074.html and http://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/using.html it sounds like CancelIo() is not really usable. Must customer requires Windows XP support. What are my options?
NOTE: I am reading from a serial port.
CancelIo() works fine. I misunderstood my code.
Upon further investigation it turns out that the code was invoking CancelIo() followed by ReadFile() with a timeout INFINITE. The completion port was never getting notified of the read because the remote end was never sending anything. In other words, CancelIo() did not cancel subsequent operations.
I found some eye-opening documentation here:
Be careful when coding for asynchronous I/O because the system reserves the right to make an operation synchronous if it needs to. Therefore, it is best if you write the program to correctly handle an I/O operation that may be completed either synchronously or asynchronously. The sample code demonstrates this consideration.
It turns out that device drivers may choose to treat an asynchronous operation in a synchronous manner if the data being read is already cached by the device driver. Upon further investigation, I discovered that when CancelIo() was being invoked before ReadFile() it would sometimes cause the latter to return synchronously. I have no idea why the completion port was never getting notified of ReadFile() after a CancelIo() but I can no longer reproduce this problem.
The completion port is signaled regardless of whether ReadFile() is synchronous or asynchronous.
Wait on (possibly with zero timeout) overlapped.Handle. It will be set whether the operation is completed or cancelled.
If you're already using overlapped operations, why do you need to cancel I/O at all? The entire concept of 'cancelling' an in-flight I/O operation is really race-prone, and totally subject to the underlying device stack you're trying to write to; really the only time you'd want to do this is to unblock another thread who is waiting on the completion of that I/O.
It is possible to write asynchronous I/O code without CancelIo function. The question depends on the scenario you are using CancelIO. Let's say that you need to implement file reading thread. Thread pseudo-code:
for(;;)
{
ReadFile(port, buffer, length, &bytesTransferred, overlapped);
WaitForMultipleObjects( overlapped event + stop event);
if ( stop event is signaled )
break;
if (overlapped event is signaled )
handle ReadFile results
}
Such thread reads file (socket, port etc.) using overlapped I/O. Most of the time it waits on WiatForMultipleObjects line. It wakes up when new data is available, or stop event is signaled. To stop this thread, set stop event from another thread. CancelIO is not used.

WaitForSingleObject on a file handle?

What happens when you call WaitForSingleObject() on a handle you've created with CreateFile() or _get_osfhandle()?
For reasons not worth explaining I would like to use WaitForSingleObject() to wait on a HANDLE that I've created with _get_osfhandle(fd), where fd comes from a regular call to _open(). Is this possible?
I have tried it in practice, and on some machines it works as expected (the HANDLE is always in the signaled state because you can read more data from it), and on some machines WaitForSingleObject() will block indefinitely if you let it.
The MSDN page for WaitForSingleObject() says that the only supported things that it handles are "change notifications, console input, events, memory resource notifications, mutex, processes, semaphores, threads, and waitable timers."
Additionally, would it be different if I used CreateFile() instead of _get_osfhandle() on a CRT file descriptor?
Don't do it. As you can see, it has undefined behavior.
Even when the behavior is defined, it's defined in such a way as to be relatively not useful unless you don't like writing additional code. It is signaled when any asynchronous I/O operation on that handle completes, which does not generalize to tracking which I/O operation finished.
Why are you trying to wait on a file handle? Clearly the intent matters when you are doing something that isn't even supported well enough to not block indefinitely.
I found the following links. The concensus seems to me, don't do it.
Asynch IO explorer
Waiting on a file handle
When an I/O operation is started on an
asynchronous handle, the handle goes
into a non-signaled state. Therefore,
when used in the context of a
WaitForSingleObject or
WaitForMultipleObjects operation, the
file handle will become signaled when
the I/O operation completes. However,
Microsoft actively discourages this
technique; it does not generalize if
there exists more than one pending I/O
operation; the handle would become
signaled if any I/O operation
completed. Therefore, although this
technique is feasible, it is not
considered best practice.
Egghead Cafe:
Use ReadDirectoryChangesW in
overlapped mode. WaitForSingleObject
can wait on the event in the
OVERLAPPED struct.
You can also use the API
WaitForSingleObject() to wait on a
file change if you use the following
change notification function:
FindFirstChangeNotification()
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/findfirstchangenotification.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitforsingleobject.asp
An interesting note on "evilness" of ReadDirectoryChangesW:
http://blogs.msdn.com/ericgu/archive/2005/10/07/478396.aspx

Resources