• Re: Where to close the channel

    From Rich@21:1/5 to Luis Mendes on Wed Apr 24 20:40:59 2024
    Luis Mendes <[email protected]> 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Leitgeb@21:1/5 to Rich on Thu Apr 25 21:59:30 2024
    Rich <[email protected]d> wrote:
    Luis Mendes <[email protected]> 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)