I have an application running on Windows XP, using
Tcl/Tk 8.4.3
and BLT 2.4Z and built using Visual C++ 6.
When I run the application under the msdev debugger,
each use of blt::bgexec
triggers a debugger error. These are reproducable in
bltsh.exe and are reported as:
First-chance exception in bltsh.exe (NTDLL.DLL):
0xC0000008: invalid Handle.
The problem is reproducible with very simple commands
such as:
blt::bgexec q ls
When not using the debugger, there are no visible
symptoms of the problem.
I think that the exception is preventing BLT from
cleaning up the pipes
and so causing a resource leak but it's hard to prove
this.
The error is reported here:
NTDLL! 77f7592b()
7ffe0304()
Blt_DeleteFileHandler(int 1904) line 2301 + 9 bytes
CloseSink() line 856 + 12 bytes
StdoutProc(void * 0x00a914e8, int -3) line 1707 + 19
bytes
PipeEventProc(Tcl_Event * 0x00a96150, int -3) line 329
+ 17 bytes
TCL84! 004dca6a()
TCL84! 004dcdef()
BgexecCmd(void * 0x00000000, Tcl_Interp *
0x00a4a7a0, int 3, char * * 0x0026f528) line 1944 + 8
bytes
TCL84! 004809c6()
TCL84! 00481d36()
TCL84! 004af41e()
TCL84! 004ae4f7()
TCL84! 00482e24()
TCL84! 004c16c6()
TCL84! 004d8531()
main() line 195 + 19 bytes
BLTSH! mainCRTStartup + 227 bytes
KERNEL3
As often happens, the error has truncated the
traceback so the exact
point of failure is obscured. Stepping through the code
shows that
the final statement before the error is the following:
DeletePipeHandler(PipeHandler * 0x00a95cb8) line 532
Blt_DeleteFileHandler(int 1904) line 2301 + 9 bytes
CloseSink() line 856 + 12 bytes
StdoutProc(void * 0x00a914e8, int -3) line 1707 + 19
bytes
PipeEventProc(Tcl_Event * 0x00a96150, int -3) line 329
+ 17 bytes
TCL84! 004dca6a()
TCL84! 004dcdef()
BgexecCmd(void * 0x00000000, Tcl_Interp *
0x00a4a7a0, int 3, char * * 0x0026f528) line 1944 + 8
bytes
TCL84! 004809c6()
TCL84! 00481d36()
TCL84! 004af41e()
TCL84! 004ae4f7()
TCL84! 00482e24()
TCL84! 004c16c6()
TCL84! 004d8531()
main() line 195 + 19 bytes
BLTSH! mainCRTStartup + 227 bytes
KERNEL32! 77e7eb69()
There are some aspects of PipeReaderThread() that look
wrong to me, though it could be
my mis-understaning:
* the pipe will be closed with the thread reader calling:
WaitForSingleObject(pipePtr->idleEvent, INFINITE);
but the test 'pipePtr->flags & PIPE_DELETED' occurs
before the wait,
so it always goes on to try to read from the handle.
Should the order
be reversed?
* the main thread calls Tcl_EventuallyFree() on pipePtr.
PipeReaderThread() doesn't
have a Tcl_Preserve() on this, so can it safely
dereference pipePtr in its
final iteration?
Unfortunately, I didn't manage to resolve the exception
problem
Logged In: NO
I am seeing this error as well, and think it is causing
problems.
But I don't think the problem is with the PipeReaderThread
as suggested. That test on PIPE_DELETED should never occur
in normal operation. I think it would take an exceptional
condition to hit it. Normally, an EOF or error will occur
from the ReadFile and the ExitThread(0) will kick in before
you get around to that test again.
I also don't think the PipeReadThread needs to have a
TclPreserve on the pipePtr. I think there are other checks
in the event sequencing that prevent the DeletePipeHandler
from being called while the thread is still going. But I
could be wrong on this.
Logged In: NO
I believe this occurs because CloseSink (in bltBgexec.c)
does "close(sinkPtr->fd);" and on WIndows this means
CloseHandle((HANDLE)sinkPtr->fd, from the #ifdef WIN32
#define. Then, a few lines later CloseSink calls
Tcl_DeleteFileHandler, which on Windows is
BltDeleteFileHandler. Blt_DeleteFileHandler in turn calls
DeletePipeHandler which calls CloseHandle(pipePtr->hPipe).
but pipePtr->hPipe is our good friend sinkPtr->fd, which
apparently has already been closed enough, thus the debug
message. I tried commenting out the first close, and the
message goes away. Now to figure out if that is appropriate
for Windows (I think it is), and for Linux (might not be,
because the closing is different there).