newbietcl
newbietcl

Reputation: 11

TCL: Can we use exec to run a program in background, and yet capture the error codes appropriately?

Using TCL, I am trying to use the "try" command in TCL as a background process and return the error codes. However, using the ampersand (&) always returns the error code as 0 indicating a successful run.

try {
        exec cmd /c test.exe &
        set returnvalue 0
    } on ok {output} {
        puts "Command successful"
    } trap {CHILDSTATUS} {output options} {
        set result [lindex [dict get $options -errorcode] end]
        if {$result == 3} {
            puts "Argument undefined"
        } elseif {$result == 4} {
            puts "Login Failed"
        } elseif {$result == 1} {
            puts "Process Cancelled by user"
        }
    }

How can I instruct the interpreter to execute test.exe in the background and yet return the appropriate error codes? My intention is to run test.exe and another program in parallel, and yet read the error codes from test.exe run and post-process based on the error codes.

Any expert advices?

Upvotes: 1

Views: 682

Answers (1)

Schelte Bron
Schelte Bron

Reputation: 4813

To run processes in the background and get their exit code, you have to switch to using open "|cmd /c ... &" and fileevents. Then catch the close command (in blocking mode) for the end result:

# Helper proc to run commands in the background
proc bgexec {args} {
    set fd [open "|$args &"]
    fconfigure $fd -blocking 0
    fileevent $fd readable [list bgevent $fd [join $args]]
}

# Helper proc to handle file events
proc bgevent {fd cmd} {
    # Discard any output
    read $fd
    if {[eof $fd]} {
        fconfigure $fd -blocking 1
        try {
            close $fd
        } on ok {output} {
            puts "$cmd: Command successful"
        } trap {CHILDSTATUS} {output options} {
            set result [lindex [dict get $options -errorcode] end]
            if {$result == 3} {
                puts "$cmd: Argument undefined"
            } elseif {$result == 4} {
                puts "$cmd: Login Failed"
            } elseif {$result == 1} {
                puts "$cmd: Process Cancelled by user"
            }
        }
    }
}

bgexec cmd /c test.exe 
bgexec cmd /c test.exe arg1

vwait forever

Upvotes: 2

Related Questions