Tcl Source Code

View Ticket
Login
Ticket UUID: 419685
Title: Problem with [file channels] if std channels not available
Type: Bug Version: obsolete: 8.3.3
Submitter: mmg_kraus Created on: 2001-04-28 02:12:28
Subsystem: 27. Channel Types Assigned To: andreas_kupries
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2001-09-14 07:14:05
Resolution: None Closed By: andreas_kupries
    Closed on: 2001-09-14 00:14:05
Description:
This occurs whenever Tcl could not initialize the 
standard channels (e.g. when it's running as a Windows 
NT service). Without any other open channels, [file 
channels] returns an empty list, which is correct. As 
soon as the first channel (e.g. a socket) is opened, 
it is registered as stdin, the next one as stdout, the 
third one as stderr. [file channels] returns {stdin 
stdout stderr}. Any additional open channel is 
returned with its Tcl name, e.g. sock123.

The problem is that I don't know how to prevent the 
first three sockets to be registered as the standard 
channels, and that [file channels sock*] does not 
return the list of all open sockets. (As a workaround, 
I create three dummy channels that do nothing.)

The man page for TclGetStdChannel sort of talks about 
that behavior, but only if "one of the standard 
channels is set to NULL, either by calling 
Tcl_SetStdChannel with a null channel argument, or by 
calling Tcl_Close on the channel". Since I'm doing 
pure Tcl here, it's hard to figure out what happens 
internally. Is this really the desired behavior of Tcl?

Looking at tclIO.c, I find that in Tcl_GetStdChannel() 
the statement "tsdPtr->stdinInitialized = 1" is done 
unconditionally, even when the preceeding "tsdPtr-
>stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN)" 
returns NULL. This is the reason why, at the end of 
Tcl_CreateChannel(), the first programatically created 
channel is automatically registered as stdin, the next 
as stdout etc., even though these standard channels 
weren't really initialized (because they couldn't be 
obtained).

This conflicts with the documentation, since neither 
Tcl_SetStdChannel() was called with NULL, nor was 
Tcl_Close() called.

Proposed fix: In TclGetStdChannel(), do the "tsdPtr-
>stdinInitialized = 1" only when 
TclpGetDefaultStdChannel(TCL_STDIN) returned != NULL 
(and similar for stdout and stderr). That is, move 
those lines down a bit into the already existing if() 
statements. Is this the right solution (or is there 
not even a problem ;-)?

Diff for tclIO.c:

332d331
< tsdPtr->stdinInitialized = 1;
343a343
>             tsdPtr->stdinInitialized = 1;
353d352
< tsdPtr->stdoutInitialized = 1;
354a354
>             tsdPtr->stdoutInitialized = 1;
364d363
< tsdPtr->stderrInitialized = 1;
365a365
>             tsdPtr->stderrInitialized = 1;
User Comments: andreas_kupries added on 2001-09-14 07:13:45:

File Added - 10759: 419685.diff.doc

Logged In: YES 
user_id=75003

Ok, enclosed a patch to the new manpage "StdChannels.3".

It describes how the proposed change would affect the 
handling of the tcl standard channels. This should help in 
the further evaluation if this change is desirable or not.

andreas_kupries added on 2001-08-25 06:27:42:

File Added - 9960: 419685.diff

Logged In: YES 
user_id=75003

Enclosed a true patch against the CVS head.

hobbs added on 2001-05-22 08:57:09:
Logged In: YES 
user_id=72656

It is a standard convention that when the std channels are 
closed, the next following channels to be opened will be 
assumed as new std channels.

The question here is really whether we are correctly 
handling the std channels when they aren't initially 
opened.  I believe this would also affect Tcl when run as a 
unix daemon in certain cases, and the logic should be 
checked there.

I guess it is plausible to argue that the behavior is still 
correct, and the docs need updating with "or the std 
channels were unable to be created at startup".  However, I 
can see the aliasing behavior to be very disconcerting.  My 
initial suggestion is that the valid way to work this would 
be:

if {[llength [file channels std*]] != 3} {
# create bogus channels to add up to 3
}

mmg_kraus added on 2001-05-03 09:34:01:
Logged In: YES 
user_id=206503

The patch works as expected (I tested this before I created 
this bug report and did it again today). I get my standard 
channels in a regular application (well, [gets stdin] in 
wish doesn't work with or without patch), and I get a clean 
[file channels] list when it runs as a service. I don't see 
why a standard channel is considered initialized when the 
function to obtain it returned NULL (essentially saying 
that I didn't get the standard channel). Guess it's just a 
little bug.

andreas_kupries added on 2001-05-02 21:30:56:
Logged In: YES 
user_id=75003

Please test your patch with a local copy of the tcl core. I
believe that with your patch an interpreter like tclsh or
wish will not initiialize its standard channels at all, even
if they are available.

We have here an undocumented dependency between the tcl
library and the application using it. The library expects
that the first three channels opened by the application are
the standard channels. This is true for tclsh and wish but
obviously not for the NT service wrapper.

Another workaround might be to define a "null" channel type
and have the NT service wrapper create three such null
channels.

We should update the documentation too.

Attachments: