From 13fd7884410510c20f77bdd1204d60a419eb7ac4 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 9 Jun 2012 19:36:31 +0100 Subject: [PATCH] subproc --- applet.tcl | 40 ------------------------------------ example | 3 ++- subproc.tcl | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 subproc.tcl diff --git a/applet.tcl b/applet.tcl index 2bb9ac4..8a0193f 100644 --- a/applet.tcl +++ b/applet.tcl @@ -218,43 +218,3 @@ proc setupinnerwindow {w} { proc setimage {image} { .i configure -image $image } - -proc fork-then {ondeath inchild} { - global children errorCode errorInfo - foreach f {stdout stderr} { - if {[catch { flush $f } emsg]} { - catch { bgerror $emsg } - } - } - set pid [fork] - if {!$pid} { - if {[catch { - uplevel 1 $inchild - } emsg]} { - puts stderr "CHILD ERROR $emsg\n$errorCode\n$errorInfo\n" - } - kill KILL [id process] - } - set children($pid) $ondeath - return $pid -} - -proc chld-handler {} { - global children - while 1 { - if {[catch { set got [wait -nohang] }]} break - if {![llength $got]} break - manyset $got pid how how2 - if {[info exists children($pid)]} { - set l $children($pid) - unset children($pid) - if {[catch { - uplevel #0 [concat [list $l] $how $how2] - } emsg]} { - catch { bgerror $emsg } - } - } - } -} - -signal -restart trap CHLD { after idle chld-handler } diff --git a/example b/example index 8c5e0c9..b719c50 100755 --- a/example +++ b/example @@ -2,6 +2,7 @@ # -*- Tcl -*- source applet.tcl +source subproc.tcl #----- menu ----- @@ -68,7 +69,7 @@ proc run-child {} { } set status none - set status [fork-then child-died { + set status [subproc::fork child-died { execl xacpi-simple [list -into [winfo id .i.i.b.c]] }] puts "FORKED $status" diff --git a/subproc.tcl b/subproc.tcl new file mode 100644 index 0000000..36d5465 --- /dev/null +++ b/subproc.tcl @@ -0,0 +1,59 @@ + +namespace eval subproc { + +#----- general purpose subprocess handling ----- +# +# One useful procedure: +# subprocess::fork ONDEATH INCHILD +# forks, evaluates INCHILD in the calling context but in the child +# and when the child dies evaluates [concat [list ONDEATH] W2 W3] +# where W2 and W3 are the 2nd and 3rd elements of the list returned +# by tclx's wait. +# +# INCHILD should not return; if it does or if it gets an error, the +# result is that the child gets a SIGKILL. + +variable children + +proc fork {ondeath inchild} { + variable children + global errorCode errorInfo + foreach f {stdout stderr} { + if {[catch { flush $f } emsg]} { + catch { bgerror $emsg } + } + } + set pid [::fork] + if {!$pid} { + if {[catch { + uplevel 1 $inchild + } emsg]} { + puts stderr "CHILD ERROR $emsg\n$errorCode\n$errorInfo\n" + } + kill KILL [id process] + } + set children($pid) $ondeath + return $pid +} + +proc chld-handler {} { + variable children + while 1 { + if {[catch { set got [wait -nohang] }]} break + if {![llength $got]} break + manyset $got pid how how2 + if {[info exists children($pid)]} { + set l $children($pid) + unset children($pid) + if {[catch { + uplevel #0 [concat [list $l] $how $how2] + } emsg]} { + catch { bgerror $emsg } + } + } + } +} + +signal -restart trap CHLD { after idle subproc::chld-handler } + +} -- 2.30.2