WARNING: Long script ahead.
A while ago, I faced a similar problem: from a Tcl script, launch a number of processes, then wait for all of them to finish. Here is a demo script I wrote to solve this problem.
main.tcl
#!/usr/bin/env tclsh
package require Tclx;
proc updatePidList {stat} {
global pidList
global allFinished
lassign $stat processId howProcessEnded exitCode
set pidList [lindex [intersect3 $pidList $processId] 0]
set processCount [llength $pidList]
set updatedPidList {}
foreach pid $pidList {
if {![catch {exec ps $pid} errmsg]} {
lappend updatedPidList $pid
}
}
set pidList $updatedPidList
if {$processCount > 0} {
puts "Waiting for [llength $pidList] processes"
} else {
set allFinished 1
puts "All finished"
}
}
proc childTerminated {} {
signal -restart trap SIGCHLD childTerminated
while {![catch {wait -nohang} stat] && $stat ne {}} {
after idle [list updatePidList $stat]
}
}
puts "Main begins"
set NUMBER_OF_PROCESSES_TO_LAUNCH 10
set pidList {}
set allFinished 0
signal -restart trap SIGCHLD childTerminated
for {set i 0} {$i < $NUMBER_OF_PROCESSES_TO_LAUNCH} {incr i} {
set childId [exec tclsh child.tcl $i &]
puts "child #$i, pid=$childId"
lappend pidList $childId
after 1000
}
puts "list of processes: $pidList"
puts "Waiting for child processes to finish"
vwait allFinished
puts "Main ends"
child.tcl
proc randomInteger {min max} {
return [expr int(rand() * ($max - $min + 1) * 1000 + $min)]
}
set duration [randomInteger 10 30]
puts " child #$argv runs for $duration miliseconds"
after $duration
puts " child #$argv ends"
Sample output for running main.tcl
Main begins
child #0, pid=64525
child #0 runs for 17466 miliseconds
child #1, pid=64526
child #1 runs for 14181 miliseconds
child #2, pid=64527
child #2 runs for 10856 miliseconds
child #3, pid=64528
child #3 runs for 7464 miliseconds
child #4, pid=64529
child #4 runs for 4034 miliseconds
child #5, pid=64531
child #5 runs for 1068 miliseconds
child #6, pid=64532
child #6 runs for 18571 miliseconds
child #5 ends
child #7, pid=64534
child #7 runs for 15374 miliseconds
child #8, pid=64535
child #8 runs for 11996 miliseconds
child #4 ends
child #9, pid=64536
child #9 runs for 8694 miliseconds
list of processes: 64525 64526 64527 64528 64529 64531 64532 64534 64535 64536
Waiting for child processes to finish
Waiting for 8 processes
Waiting for 8 processes
child #3 ends
Waiting for 7 processes
child #2 ends
Waiting for 6 processes
child #1 ends
Waiting for 5 processes
child #0 ends
Waiting for 4 processes
child #9 ends
Waiting for 3 processes
child #8 ends
Waiting for 2 processes
child #7 ends
Waiting for 1 processes
child #6 ends
All finished
Main ends
/proc
mounted, checking in there is probably the fastest way to look for a PID from pure Tcl. – Donal Fellows