killing a process in TCL

Suppose you had spawned a process in TCL and knew its PID and wanted to kill it? Sounds simple enough thing to do, right? This problem has plagued me for many months because some things you can assume on a normal system do not hold true on strange environments, such as build deaemons.

Seems simple enough, I started off with:

exec kill $pid

Except.. not every environment has the kill binary, and with that piece of code exec has to be a binary and not a shell builtin. The funny thing is that /bin/kill is in the procps package, which is the package having the buildd problems.

So next idea was to use command -v to check for the existence of kill and skip those tests that needed kill if not found. Good idea except, so I found out later, it also finds built-ins. That means we are back to problem #1.

There is a kill command in tcl, but it requires tclx. That seems excessive for just one little simple command. How can I run a shell out of TCL that runs the kill builtin? On the command line, something like below would do it.

/bin/sh -c 'kill 1234'

I was closer, but then hit TCL quoting hell. No matter what I (initially) did I’d either get the shell to complain or my variable to not be evaluated. In the end, I had to write it to a separate variable for the command line then apply that to the exec. Not perfect but at least it works now.

The resulting code (found in testsuite/config/unix.exp) looks like:

proc kill_process pid {
    set cmdline "kill $pid"
    if { [catch { exec /bin/sh -c $cmdline } msg]} {
        warning "Could not kill process: $msgn"
    }
}

Perhaps there is a more elegant way, I’m certainly no star TCL programmer, but of all the combinations I saw this was the only that worked.