From 7287ebb84338db042f47bc91b7c2f075ab8a94ed Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 9 Jun 2012 19:00:52 +0100 Subject: [PATCH] works again --- applet.tcl | 57 ++++++++++++++++++++++++++++++++++++++---- example | 72 +++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 118 insertions(+), 11 deletions(-) diff --git a/applet.tcl b/applet.tcl index 1a75f14..8440092 100644 --- a/applet.tcl +++ b/applet.tcl @@ -20,11 +20,16 @@ # which should examine b and do something appropriate. # +proc manyset {list args} { + foreach val $list var $args { + upvar 1 $var my + set my $val + } +} +package require Tclx package require tktray -#load /home/ian/things/Systray/tktray-1.3.8/libtktray1.3.8.so - wm withdraw . @@ -60,7 +65,7 @@ proc msel {} { set posted 0 } -proc innerwindow-event {why} { +proc innerwindow-resetup-required {why} { global innerwindow_after puts "IW-EVENT $why" if {[info exists innerwindow_after]} return @@ -73,6 +78,8 @@ proc innerwindow-resetup {} { puts RESETUP + innerwindow-destroying + catch { destroy .i.i.c } if {![winfo exists .i.i]} return destroy [frame .i.i.make-exist] @@ -93,7 +100,7 @@ puts RESETUP # set inner_lastw $w # set inner_lasth $h # innerwindow-ph-dummy configure -width $w -height 2 - innerwindow [winfo id .i.i.b.c] + innerwindow-ready # } } @@ -107,7 +114,7 @@ proc setupinnerwindow {w} { destroy [frame .i.make-exist] destroy [frame .i.i.make-exist] - bind .i <> { innerwindow-event "%w" } + bind .i <> { innerwindow-resetup-required IconConfigure } } bind .i { pressed %b %X %Y } @@ -167,3 +174,43 @@ proc tooltip_show {x y} { 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 4a6a16a..3b45d0b 100755 --- a/example +++ b/example @@ -16,13 +16,73 @@ image create bitmap ims -file gs_s.xbm setuptooltip settooltip "line\nanother" -proc innerwindow {id} { - puts IICONFIG - puts "IC $id" +fconfigure stdout -buffering line - .i.i.b configure -background darkblue -bd 1 -exec /home/ian/things/Chiark-utils/chiark-utils.git/cprogs/xacpi-simple \ - -into $id & +set status none + +proc innerwindow-destroying {} { + global status + puts "DESTROYING $status" + switch -exact $status { + none { } + old { } + default { kill $status; set status old } + } +} + +proc innerwindow-ready {} { + global status + puts "READY $status" + switch -exact $status { + none { + run-child + } + old { + # wait for it to die + } + default { + error "unexpected state $status" + } + } + puts "READY-done $status" +} + +set ratelimit 0 + +proc run-child {} { + global status ratelimit + + puts "RUN-CHILD $status" + set now [clock seconds] + lappend ratelimit $now + while {[lindex $ratelimit 0] < {$now - 10}} { + set ratelimit [lrange $ratelimit 1 end] + } + if {[llength $ratelimit] > 10} { + puts stderr "crashing repeatedly, quitting $ratelimit" + exit 127 + } + + set status none + set status [fork-then child-died { + execl xacpi-simple [list -into [winfo id .i.i.b.c]] + }] + puts "FORKED $status" +} + +proc child-died {how how2} { + puts "DIED $how $how2" + global status + switch -exact $status { + old { + set status none + run-child + } + default { + set status none + innerwindow-resetup-required "child died" + } + } } setupinnerwindow 40 -- 2.30.2