chiark / gitweb /
subproc
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 9 Jun 2012 18:36:31 +0000 (19:36 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 9 Jun 2012 18:36:31 +0000 (19:36 +0100)
applet.tcl
example
subproc.tcl [new file with mode: 0644]

index 2bb9ac4..8a0193f 100644 (file)
@@ -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 (executable)
--- 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 (file)
index 0000000..36d5465
--- /dev/null
@@ -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 }
+
+}