accessing a pipe from TCL and C, hang in `close/exit'

From: Ralf Fassel (ralfixx_at_gmx.de)
Date: 04/07/04


Date: Wed, 07 Apr 2004 12:46:10 +0200

tcl8.3.3, Windows 2k/XP, NutCracker sh

I have a TCL shell script which opens a socket to some remote host,
and opens a read-converter pipe (which reads from stdin). It uses
fcopy to copy data between the pipe and the socket. When the remote
host closes the socket, the script shuts down and exits.

Now I have another Tk application which opens a write pipe into that
script with stderr redirected to our stderr (so I can see the debug
messages from the script in my console)
  set fd [open "|sh path-to-script 2>@stderr" w]
  fconfigure $fd -translation binary -blocking 0

I pass the fd into C++ Code and save the Tcl_Channel for later use:
  static Tcl_Channel channel;
  ...
  channel = Tcl_GetChannel(interp, argv[1], NULL);
Later:
  Tcl_Write(channel, buf, lenght);

This works fine, data arrives on the remote host. When the remote
server ends the connection, Tcl_Write returns -1 with errno set to 32
(EPIPE). Now I want to close the channel from C++:

  Tcl_SetChannelOption(interp, channel, "-blocking", "true");
  Tcl_UnregisterChannel(interp, channel);

Unfortunately, this hangs as if there was some command in the pipe
still running and we were waiting for it to exit. However, in the
taskmanager I don't see any left-over programs.

If I omit the switch to blocking mode before the `unregister', the
program continues, but subsequently hangs in `exit'.

If I do the `close' from TCL (fconfigure $channel -blocking 1; close
$channel), the program does not seem to hang.

Question: is the Tcl_UnregisterChannel(interp, channel) equivalent to
`close $channel', or do I have to do something else here?

R'