Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

"The hands that help are better far than the lips that pray." -- Robert G. Ingersoll


devel / comp.lang.tcl / Where to close the channel

SubjectAuthor
* Where to close the channelLuis Mendes
+* Re: Where to close the channelRich
|`- Re: Where to close the channelAndreas Leitgeb
`- Re: Where to close the channelEmiliano

1
Where to close the channel

<66292cf2$0$709$14726298@news.sunsite.dk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=13320&group=comp.lang.tcl#13320

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!i2pn.org!usenet.goja.nl.eu.org!dotsrc.org!filter.dotsrc.org!news.dotsrc.org!not-for-mail
From: luisXXXl...@gmail.com (Luis Mendes)
Subject: Where to close the channel
Newsgroups: comp.lang.tcl
MIME-Version: 1.0
User-Agent: Pan/0.154 (Izium; 517acf4)
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Date: 24 Apr 2024 16:01:54 GMT
Lines: 53
Message-ID: <66292cf2$0$709$14726298@news.sunsite.dk>
Organization: SunSITE.dk - Supporting Open source
NNTP-Posting-Host: 57212719.news.sunsite.dk
X-Trace: 1713974514 news.sunsite.dk 709 luislupe@gmail.com/176.79.85.73:56424
X-Complaints-To: staff@sunsite.dk
 by: Luis Mendes - Wed, 24 Apr 2024 16:01 UTC

Hi,

I'm using an async channel to read the log from an external command.

The code skeleton is like this:

while {[llength $in_queue] > 0} {
nsc::runCommand $exec_id
vwait ::exit_flag
}

namespace eval nsc {
proc runCommand {exec_id} {
set run_${exec_id} [Parse new $exec_id]
}

oo::class create Parse {
variable chan_ans
constructor {exec_id} {
set chan_ans [open ![list {*}$comm] r]
chan configure $chan_ans -blocking 0 -buffering line
chan event $chan_ans readable [list [self object] parseLine]
}
method parseLine {} {
set status [catch {chan gets $chan_ans line} nchars]
.....
if {$status || [chan eof $chan_ans]} {
# all received
chan configure $chan_ans -blocking 1 # to assure all is
written
chan event $chan_ans readable {}
chan close $chan_ans
set ::exit_flag 1
}
}
}

But the script never finishes, seems to complain at the line
'chan close $chan_ans'.

In the book "The Tcl Programming Language", by Ashok, in page 437 (466 of
the PDF) there's this:
"When an end of file is seen on a channel, it is crucial to EITHER remove
the read handler from the channel aw we have done, or to close the channel
in the handler itself before returning.
Otherwise, the channel will continuously raise readable events because the
channel is at end of file."

Are the chan event readable {} and chan close incompatible?
So, what should I do to correct this issue?

Luis

Re: Where to close the channel

<v0bqor$2hdf3$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=13321&group=comp.lang.tcl#13321

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ric...@example.invalid (Rich)
Newsgroups: comp.lang.tcl
Subject: Re: Where to close the channel
Date: Wed, 24 Apr 2024 20:40:59 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 66
Message-ID: <v0bqor$2hdf3$1@dont-email.me>
References: <66292cf2$0$709$14726298@news.sunsite.dk>
Injection-Date: Wed, 24 Apr 2024 22:40:59 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="5149b121e7cb7fb9b8b6c8705aaef0f4";
logging-data="2668003"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/bVhdVro+hTSq+cSFCf0c9"
User-Agent: tin/2.6.1-20211226 ("Convalmore") (Linux/5.15.139 (x86_64))
Cancel-Lock: sha1:xnXs1Qsgi/RK2TPHb6KKFHu7Z+U=
 by: Rich - Wed, 24 Apr 2024 20:40 UTC

Luis Mendes <luisXXXlupeXXX@gmail.com> wrote:
> Hi,
>
> I'm using an async channel to read the log from an external command.
>
> The code skeleton is like this:

And includes a syntax error (missing brace).

> namespace eval nsc {
> proc runCommand {exec_id} {
> set run_${exec_id} [Parse new $exec_id]
> }
>
> oo::class create Parse {
> variable chan_ans
> constructor {exec_id} {
> set chan_ans [open ![list {*}$comm] r]
> chan configure $chan_ans -blocking 0 -buffering line
> chan event $chan_ans readable [list [self object] parseLine]
> }
> method parseLine {} {
> set status [catch {chan gets $chan_ans line} nchars]
> .....
> if {$status || [chan eof $chan_ans]} {
> # all received
> chan configure $chan_ans -blocking 1 # to assure all is written

Syntax error. Tcl is not bash, you only get to insert a comment using
# where Tcl's expecting a command. So 'same line' comments have to
terminate the current command first (with a ;) and then the comment can
start. The above line needs to read:

chan configure $chan_ans -blocking 1 ;# to assure all is written

To avoid the syntax error. And once the syntax error is fixed, and a
missing } inserted, your code works just fine.

Number two, given that you have a read only channel open in this code
example, there is no need to flip to blocking, as there is no 'write
data' in a read only channel.

> chan event $chan_ans readable {}

Unnecessary if you are going to also close the channel, as closing the
channel takes care of removing the readable event.

> chan close $chan_ans
> set ::exit_flag 1
> }
> }
> }
>
> But the script never finishes, seems to complain at the line
> 'chan close $chan_ans'.

It never finishes because the syntax error from the incorrect inline
comment aborts the event call, such that no more event calls happen, so
there's never another entry to your object to ultimately set the vwait
variable and abort the script.

> So, what should I do to correct this issue?

Fix the comment syntax error (which was all I needed to fix to make the
example you posted work properly). I'm assuming the missing close
brace (}) was a copy/paste omission here.

Re: Where to close the channel

<20240424225025.52f44a6ad91b05e38ca80e69@gmail.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=13323&group=comp.lang.tcl#13323

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: emil.gav...@gmail.com (Emiliano)
Newsgroups: comp.lang.tcl
Subject: Re: Where to close the channel
Date: Wed, 24 Apr 2024 22:50:25 -0300
Organization: A noiseless patient Spider
Lines: 96
Message-ID: <20240424225025.52f44a6ad91b05e38ca80e69@gmail.com>
References: <66292cf2$0$709$14726298@news.sunsite.dk>
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Injection-Date: Thu, 25 Apr 2024 03:50:29 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="d93972cce2f981de6dabd2d63db86ed1";
logging-data="2789261"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/mT4x0vstZdIm6f/TAB1I1D+2GewTCXVI="
Cancel-Lock: sha1:W1vPVbDIm7AbeALSnkpmrIAQwhs=
X-Newsreader: Sylpheed 3.5.1 (GTK+ 2.24.32; i686-pc-linux-gnu)
 by: Emiliano - Thu, 25 Apr 2024 01:50 UTC

On 24 Apr 2024 16:01:54 GMT
Luis Mendes <luisXXXlupeXXX@gmail.com> wrote:

> Hi,
>
> I'm using an async channel to read the log from an external command.
>
> The code skeleton is like this:
>
> while {[llength $in_queue] > 0} {
> nsc::runCommand $exec_id
> vwait ::exit_flag
> }
>
> namespace eval nsc {
> proc runCommand {exec_id} {
> set run_${exec_id} [Parse new $exec_id]
> }
>
> oo::class create Parse {
> variable chan_ans
> constructor {exec_id} {
> set chan_ans [open ![list {*}$comm] r]
> chan configure $chan_ans -blocking 0 -buffering line
> chan event $chan_ans readable [list [self object] parseLine]
> }
> method parseLine {} {
> set status [catch {chan gets $chan_ans line} nchars]
> .....
> if {$status || [chan eof $chan_ans]} {
> # all received
> chan configure $chan_ans -blocking 1 # to assure all is
> written
> chan event $chan_ans readable {}
> chan close $chan_ans
> set ::exit_flag 1
> }
> }
> }
>
> But the script never finishes, seems to complain at the line
> 'chan close $chan_ans'.

If the command $comm writes to stderr, or returns a value != 0, then
[chan close] will raise an error, as shown in this interactive session:

% set fd [open |[list /bin/sh -c {echo "test"; echo "error" >&2}] r]
file6
% chan read $fd
test

% catch {chan close $fd} e o
1
% set e
error
% set o
-code 1 -level 0 -errorstack {INNER {invokeStk1 ::tcl::chan::close file6}} -errorcode NONE -errorinfo {error
while executing
"chan close $fd"} -errorline 1

The code pattern I would use in such case is

if {[chan gets $chan_ans line] < 0} {
if {[chan eof $chan_ans]} {
# use [catch] to avoid errors in closing the pipeline
catch {chan close $chan_ans}
set ::exit_flag 1
}
return
}
# process $line

> In the book "The Tcl Programming Language", by Ashok, in page 437 (466 of
> the PDF) there's this:
> "When an end of file is seen on a channel, it is crucial to EITHER remove
> the read handler from the channel aw we have done, or to close the channel
> in the handler itself before returning.
> Otherwise, the channel will continuously raise readable events because the
> channel is at end of file."
>
> Are the chan event readable {} and chan close incompatible?
> So, what should I do to correct this issue?

The book is (unsurprisingly) correct; closing the channel inside the handler
is the right thing to do.
In your case, while the channel gets closed and the event handler unregistered,
the line

set ::exit_flag 1

is never executed because the previous line raises an error as explained above.

Hope this helps.

--
Emiliano <emil.gavilan@gmail.com>

Re: Where to close the channel

<slrnv2lki2.23q10.avl@logic.at>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=13324&group=comp.lang.tcl#13324

  copy link   Newsgroups: comp.lang.tcl
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: avl...@logic.at (Andreas Leitgeb)
Newsgroups: comp.lang.tcl
Subject: Re: Where to close the channel
Date: Thu, 25 Apr 2024 21:59:30 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 94
Message-ID: <slrnv2lki2.23q10.avl@logic.at>
References: <66292cf2$0$709$14726298@news.sunsite.dk>
<v0bqor$2hdf3$1@dont-email.me>
Reply-To: avl@logic.at
Injection-Date: Thu, 25 Apr 2024 23:59:30 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="e4edf1fbb32ea1cb4e6fd14be1451b95";
logging-data="3405100"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+pxA7+3Owloit5D64dsRDH"
User-Agent: slrn/1.0.3 (Linux)
Cancel-Lock: sha1:OFkevsyzQPaOKJS1XibijTihnJo=
 by: Andreas Leitgeb - Thu, 25 Apr 2024 21:59 UTC

Rich <rich@example.invalid> wrote:
> Luis Mendes <luisXXXlupeXXX@gmail.com> wrote:
>> Hi,
>> I'm using an async channel to read the log from an external command.
>> The code skeleton is like this:
> And includes a syntax error (missing brace).

There are two more... inserted below...
>
>> namespace eval nsc {
>> proc runCommand {exec_id} {
>> set run_${exec_id} [Parse new $exec_id]
>> }
>>
>> oo::class create Parse {
>> variable chan_ans
>> constructor {exec_id} {
>> set chan_ans [open ![list {*}$comm] r]

to create a pipe-channel, the first char of the "filename" needs
to be a pipe char ("|"), not an exclamation mark!

It is possible that this exclam is really just caused by some newsclient
going berserk and wildly replacing characters... If it were in original
code, then it would likely not even get as far as the "chan close" line,
but instead already bomb here in the constructor ...

Also, I don't see where the variable "comm" comes from. Maybe the
part defining it has been trimmed since the OP, otherwise variable
comm needs to be defined somewhere and eventually made known within
the constructor... (at least, if it is a global or namespace-
variable - not sure about class members)

>> chan configure $chan_ans -blocking 0 -buffering line
>> chan event $chan_ans readable [list [self object] parseLine]
>> }
>> method parseLine {} {
>> set status [catch {chan gets $chan_ans line} nchars]
>> .....
>> if {$status || [chan eof $chan_ans]} {
>> # all received
>> chan configure $chan_ans -blocking 1 # to assure all is written
>
> Syntax error. Tcl is not bash, you only get to insert a comment using
> # where Tcl's expecting a command. So 'same line' comments have to
> terminate the current command first (with a ;) and then the comment can
> start. The above line needs to read:
>
> chan configure $chan_ans -blocking 1 ;# to assure all is written
>
> To avoid the syntax error. And once the syntax error is fixed, and a
> missing } inserted, your code works just fine.
>
> Number two, given that you have a read only channel open in this code
> example, there is no need to flip to blocking, as there is no 'write
> data' in a read only channel.

Not quite... making the command channel blocking before the close
is necessary to capture the exit-code of the pipeline process.

>> chan event $chan_ans readable {}
>
> Unnecessary if you are going to also close the channel, as closing the
> channel takes care of removing the readable event.
>
>> chan close $chan_ans

But for that, the "chan close" had better be wrapped in a catch or
try statement, in order to handle non-zero exit codes from child.
Otherwise, a non-zero exit code from child process would just bomb
out of the tcl script, and skip setting the following variable.

>> set ::exit_flag 1
>> }
>> }
>> }
>> But the script never finishes, seems to complain at the line
>> 'chan close $chan_ans'.

Most likely, the child process actually returns non-zero.
So, tcl throws an exception from the "close".

> It never finishes because the syntax error from the incorrect inline
> comment aborts the event call, such that no more event calls happen, so
> there's never another entry to your object to ultimately set the vwait
> variable and abort the script.
>
>> So, what should I do to correct this issue?
>
> Fix the comment syntax error (which was all I needed to fix to make the
> example you posted work properly). I'm assuming the missing close
> brace (}) was a copy/paste omission here.


devel / comp.lang.tcl / Where to close the channel

1
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor