How to check if a thread waits for data at the read-end of a pipe?
From: Leif Erik Larsen (leifel_at_online.no)
Date: 11/25/04
- Next message: Arkady Frenkel: "Re: How to check if a thread waits for data at the read-end of a pipe?"
- Previous message: Arkady Frenkel: "Re: LoadLibrary race/deadlock"
- Next in thread: Arkady Frenkel: "Re: How to check if a thread waits for data at the read-end of a pipe?"
- Reply: Arkady Frenkel: "Re: How to check if a thread waits for data at the read-end of a pipe?"
- Messages sorted by: [ date ] [ thread ]
Date: Thu, 25 Nov 2004 11:06:49 +0100
After many tens of hours of searching Google, scanning programming
groups, etc, I am almost about to give up. The only thing I have found
is that there are (or at least has been) others struggling to find the
answer to the same question as me, which makes me think that this is in
fact something that is impossible, or at least difficult-, to do on
Win32. So let me make some noice here once more, hopefully being more
specific this time....
I am about to port a C++ application (Larsen Commander) from OS/2 to
Win32 and in the Win32 version I need a way to check (or get notified)
when a thread or a process is waiting for data to be available at the
read-end of my pipe. OS/2 has the API DosSetNPipeSem() that lets me
attach a semaphore to a named pipe and I can then use the other API
DosQueryNPipeSemState() to check if there is someone waiting at the
read-end of the pipe. I guess Win32 has a way to let me do the same, but
I am not able to find out how to do this using the standard Win32 SDK
documentation. Anyone that can help?
My application acts as a GUI command line shell in this regard. It has a
console monitor and a command line where the user can launch internal
and extarnal commands in the same way as with CMD.EXE. Larsen Commander
launches command line programs as child processes, and redirects the
child's STDIN, STDOUT and STDERR streams in standard documented ways.
Everything works just great, except when it comes to one thing: When the
child process attempts to read data from its STDIN it enters a
wait-state because its STDIN-stream is empty. What I want to do in my
application then is to show the command line in a special color mode, so
the user can type some text of which to write to the pipe that feeds the
childs STDIN. However, I find no way to check if there is someone at the
read-end of the pipe waiting for data.
Luckily (for my application and its users on Windows) most command line
programs will never attempt to read anything from its STDIN, but some
programs do. One example is UNZIP.EXE, which needs to get confirmations
from the user (STDIN) e.g. before overwriting a file on the file system.
UNZIP.EXE does this by reading from its STDIN.
To be clear: The only information I need in order for this to work is a
way to check if there is someone waiting for data at the read-end of my
pipe.
I am currently using an anonymous pipe created with Win32::CreatePipe(),
but if I need to, and if it is possible, I can of course rewrite this to
use a named pipe created with Win32:CreateNamedPipe(), or anything else.
The best would be a way that is possible to work on all flavours of
Win32, but it is also acceptible for me to use a technique only
available on Win2000/XP.
Remember: My application is a GUI application. Thus, I cannot use any
console-based technique for this, as far as I can see.
What I have tried are (code fragments only):
1) Using Win32::WaitForSingleObject() on the pipe file handle(s).
------------------------------------------------------------------
// This doesn't seem to work (res will never be WAIT_TIMEOUT):
HANDLE childStdInWriteSide = ...;
HANDLE childStdInReadSide = ...;
DWORD res = Win32::WaitForSingleObject(childStdInWriteSide, 0);
if (res == WAIT_TIMEOUT) // If child wait for data at read-end?
return true; // We never reach here! :-(
else
return false;
// This doesn't work either (gives error "invalid handle"):
HANDLE childStdInWriteSide = ...;
HANDLE childStdInReadSide = ...;
DWORD res = Win32::WaitForSingleObject(childStdInReadSide, 0);
if (res == WAIT_TIMEOUT) // If child wait for data at read-end?
return true; // We never reach here! :-(
else
return false;
2) Using Win32::NtQuerySystemInformation() to check the
state of the child process thread(s).
--------------------------------------------------------
// This doesn't work (child process thread wait state
// seems to be unstable).
LPVOID infoBuff = ...;
NtQuerySystemInformation(NT_PROCESSTHREAD_INFO, infoBuff, ...);
PSYSTEM_PROCESSES p = (PSYSTEM_PROCESSES) infoBuff;
for (;;)
{
if (p->ProcessId == myChildProcessInfo.dwProcessId)
{
// We have found the information for the child process of ours.
int threadCount = p->ThreadCount;
for (int i=0; i<threadCount; i++)
{
SYSTEM_THREADS* t = &p->Threads[i];
if (t->State == StateWait &&
(t->WaitReason == Executive ||
t->WaitReason == WrLpcReply))
{
// This happens also when the thread is not actually
// waiting on its STDIN, so I can't trust this.
return true;
}
}
// No need to test the remaining processes.
break;
}
if (p->NextEntryDelta <= 0)
break;
p = (PSYSTEM_PROCESSES)((char*) p + p->NextEntryDelta);
}
return false;
Thank you for reading all down to here. If you know I way to help me out
of this problem I will be very, very happy.
What about having a registration code of Larsen Commander for free? - To
the person that first provides a solution that actually works!
-- Leif Erik Larsen Author of Larsen Commander Download for Windows and OS/2 available at http://home.online.no/~leifel/lcmd/index.html
- Next message: Arkady Frenkel: "Re: How to check if a thread waits for data at the read-end of a pipe?"
- Previous message: Arkady Frenkel: "Re: LoadLibrary race/deadlock"
- Next in thread: Arkady Frenkel: "Re: How to check if a thread waits for data at the read-end of a pipe?"
- Reply: Arkady Frenkel: "Re: How to check if a thread waits for data at the read-end of a pipe?"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|