I/O aborting on thread termination...

I have an network application which uses threads and I/O
completion ports rather heavily.

It also has to read (in a non-blocking manner) from an
handle passed as the GetStdHandle(STD_INPUT_HANDLE) from
the process that started my application. (There are other
methods that can be used to pass in handles to the application
as well.)

This handle is likely either a pipe or a console handle.

Right now I start a separate thread to read this handle;
however, this thread can end up issuing write requests
on my network socket (associated with the completion
port.)

The thread also has a different life-span than the rest
of the application. (And there can be multiple instances
of this thread if the app gets passed handles via one
of the other mechanisms mentioned above.)

Now the problem: when one of these threads exits, it aborts
any outstanding I/O. Arghhhh! (Well, I should have known.)

My question is, what options do I have?

If I were, for example, to associate the thread with the
completion port, would it prevent thread exit from terminating
the I/O?

Is there any way to convert a handle to an overlapped handle?
(Since I don’t get to open the handles, I can’t assume they
I can actually use them with the completion port.)

I’m pretty sure a console handle can’t be associated with
a completion port, right?

Thanks for any insight.

Joseph

Once a thread issues i/o there is no way to move ownership of the
resulting i/o (which will be a PIRP) to another thread.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Joseph Galbraith
Sent: Thursday, July 06, 2006 5:09 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] I/O aborting on thread termination…

I have an network application which uses threads and I/O completion
ports rather heavily.

It also has to read (in a non-blocking manner) from an handle passed as
the GetStdHandle(STD_INPUT_HANDLE) from the process that started my
application. (There are other methods that can be used to pass in
handles to the application as well.)

This handle is likely either a pipe or a console handle.

Right now I start a separate thread to read this handle; however, this
thread can end up issuing write requests on my network socket
(associated with the completion
port.)

The thread also has a different life-span than the rest of the
application. (And there can be multiple instances of this thread if the
app gets passed handles via one of the other mechanisms mentioned
above.)

Now the problem: when one of these threads exits, it aborts any
outstanding I/O. Arghhhh! (Well, I should have known.)

My question is, what options do I have?

If I were, for example, to associate the thread with the completion
port, would it prevent thread exit from terminating the I/O?

Is there any way to convert a handle to an overlapped handle?
(Since I don’t get to open the handles, I can’t assume they I can
actually use them with the completion port.)

I’m pretty sure a console handle can’t be associated with a completion
port, right?

Thanks for any insight.

Joseph


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

As Doron has pointed out, user-mode IRPs cannot outlive the thread that
creates them. Probably the easiest solution is to use the thread-pool
APIs to queue the async call to an I/O worker thread. Call
QueueUserWorkItem with WT_EXECUTEINIOTHREAD. This will add one more
step to your processing path, but the async nature of QueueUserWorkItem
should fit fairly naturally with your existing async network I/O.
You’ll have to deal with work item lifetime in addition to async
operation lifetime, but this is usually easy.

There is also the little-known Win32 API function
GetThreadIOPendingFlag. This kernel call just checks to see if the
active IRP list for a particular thread (usually the caller) is empty or
not. You can use this to gauge the impact of exiting a running thread.
If you pass the WT_EXECUTEINIOTHREAD flag to the Win32 thread pool, then
the thread pool will make sure that whatever thread runs your work item
does not exit until GetThreadIOPendingFlag returns FALSE on that thread.
(Not literally returns – returns semantically, as in the lpIOIsPending
flag.)

Console handles are not kernel handles. So you are correct that they
cannot be used with I/O completion ports, or most other kernel object
APIs. The tag bits are non-zero, which is a hint to the Win32 layer
(kernel32.dll) that this is not a kernel handle, but instead is a handle
to a CSRSS console object. (Historical reasons.) The Win32 APIs
(ReadFile/WriteFile/etc.) look for this, and use LPC to communicate with
CSRSS, which is the process that manages the text consoles. When used
with consoles, these APIs really work best in synchronous mode.

– arlie

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Joseph Galbraith
Sent: Thursday, July 06, 2006 5:09 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] I/O aborting on thread termination…

I have an network application which uses threads and I/O completion
ports rather heavily.

It also has to read (in a non-blocking manner) from an handle passed as
the GetStdHandle(STD_INPUT_HANDLE) from the process that started my
application. (There are other methods that can be used to pass in
handles to the application as well.)

This handle is likely either a pipe or a console handle.

Right now I start a separate thread to read this handle; however, this
thread can end up issuing write requests on my network socket
(associated with the completion
port.)

The thread also has a different life-span than the rest of the
application. (And there can be multiple instances of this thread if the
app gets passed handles via one of the other mechanisms mentioned
above.)

Now the problem: when one of these threads exits, it aborts any
outstanding I/O. Arghhhh! (Well, I should have known.)

My question is, what options do I have?

If I were, for example, to associate the thread with the completion
port, would it prevent thread exit from terminating the I/O?

Is there any way to convert a handle to an overlapped handle?
(Since I don’t get to open the handles, I can’t assume they I can
actually use them with the completion port.)

I’m pretty sure a console handle can’t be associated with a completion
port, right?

Thanks for any insight.

Joseph


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> If I were, for example, to associate the thread with the

completion port, would it prevent thread exit from terminating
the I/O?

No.
Any thread exit will cancel all pending-and-not-yet-complete overlapped IO
issued by this thread.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com