$B!!$5$5$@$G$9!%(B
$B!!3+H/2q5D$G=P$?!VHsF14|3d$j9~$$,$3$N@h@8$-;D$k$K$O!W$H$$$&5DO@$r!$$H$j(B
$B$“$($:F|K\8l$G$^$H$a$^$7$?!%$^$@$”$^$j$^$H$^$C$F$$$J$$!J$9$$^$;$s!K$N(B
$B$G!$$9$_$^$;$s$,F|K\8l$G=P$5$;$F2<$5$$!uFM$C9~$s$G2<$5$$!%(B
$B!!$"$H$G1Q8l2=$7$?$$$H;W$$$^$9!J$7$F$/$l$k$H4r$7$$!K!%1Q8l2=$G$-$?$i!$:#(B
$B8e$O$=$C$A$H$$$&$3$H$G!%(B
$BMQ8l!‘(B
$B!&(Btrap
$B%O%s%I%i!’(Btrap$B$GEPO?$9$k%7%0%J%k$,Mh$?$H$-$K9T$&%V%m%C%/(B
$B!!!(Btrap(SIGINT){ … } $B$N(B … $BItJ,(B
$B!&HsF14|3d$j9~$!'(BThread#raise $B$d(B trap
$B%O%s%I%i$J$I!$0U?^$7$J$$(B
$B!!!%$%Y%s%H$r!$$3$3$G$OHsF14|3d$j9~$$H8F$V(B
$B!!!JB>$K$b$"$C$?$i65$($F2<$5$$!K(B
$B!&3d$j9~$_%A%'%C%/!‘HsF14|Nc30$,$"$k$+$I$&$+%A%’%C%/$7!$$b$7$"$l$P(B
$B!!!Nc30$rH/@8;I$;$?$j(B trap $B%O%s%I%i$r<B9T$7$?$j$9$k(B
$B!&%V%m%C%-%s%0=hM}!'(BI/O $B$J$I$G!$%V%m%C%/$9$k$+$b$7$l$J$$=hM}!%(B
$B35MW!‘(B
$B!!HsF14|3d$j9~$$r%A%'%C%/$9$k%?%$%%s%0$r@)8f$9$k(B primitive
$B$rDs6!$9(B
$B$k!%@)8f$N<oN`$O<!$NDL$j!$(B
$B!!!(B0. $B$J$k$Y$/IQHK$K%A%’%C%/$9$k!J$3$l$^$GDL$j$NF0:n!K(B
$B!!!(B1. $B%V%m%C%-%s%0=hM}$N%?%$%_%s%0$@$1%A%‘%C%/$9$k(B
2. $B%A%’%C%/$7$J$$(B
$B!!$?$@$7!%%A%‘%C%/$9$kNc30%/%i%9!J$NAD@h!K$O;XDj$G$-$k!%(B
$B!!$J$N$G!$(BSignalException $B!J$r7Q>5$7$?(B
Interrupt$B!K$OIQHK$K%A%’%C%/$9$k!$(B
$B$9$J$o$A(B Ctrl+C $B$O$@$$$?$$8z$/!$$7$+$7!$(BTimeoutError
$B$N$h$&$JNc30$O0BA4(B
$B$J$H$3$m$^$GCY1d$7$F=hM}$9$k$H$$$C$?5sF0$,MF0W$K5-=R$G$-$k!%(B
$BGX7J!'(B
$B!!(BThread#raise
$B$r;H$&$H!$%9%l%C%I$KBP$7$F$$$m$s$J$A$g$C$+$$$r=P$9$3$H$,(B
$B$G$-$k!%$^$?!$(Btrap(signal){…}
$B$H$9$k$H!$G$0U$N%7%0%J%k$K$D$$$FBP1~$9$k(B
$B$3$H$,$G$-$k!%(B
$BNc(B1
th = Thread.new{
begin
…
rescue NantokaError
…
end
}
th.raise(NantokaError) #=> th $B$K(B NantokaError
$B$r6/@)E*$K0z$-5/$3$9(B
$BNc(B2
q = Queue.new
th1 = Thread.new{
q << calc_in_algorithm1
}
th2 = Thread.new{
q << calc_in_algorithm2
}
result = q.pop
th1.raise(TerminateCalcError)
th2.raise(TerminateCalcError)
$B%"%k%4%j%:%`(B1$B!$(B2 $B$G7W;;$7$F!$$I$A$i$+@h$KEz$($,=P$?$i!$(B
$B$b$&(B1$B$D$N$[$&$r;_$a$k(B
$BNc(B3
trap(SIGINT){
# $B2?$+8e=hM}(B
}
trap(SIGHUP){
# $B2?$+(B reload $B=hM}(B
}
server_exec # $B%5!<%P$N=hM}(B
$B!!$J$!$8=:$N3d$j9~$%A%'%C%/$O!$(BRUBY_VM_CHECK_INTS()
$B$G9T$C$F$$j!$%a(B
$B%=%C%I$N5/F0;~!$%j%?!<%s;~!$A0J}$X$N%8%c%s%W;~!$%V%m%C%-%s%0=hM}$NA08e$G(B
$B9T$C$F$$$k!%(B
$BLdBjE@!'(B
$B!!(BThread#raise
$B$@$H$+$,>e$,$C$F$/$k%?%$%_%s%0$O@)8f$G$-$J$$$N$G!$Nc$($P(B
ensure $BCf$G8e=hM}$r$7$F$$$?>l9g$K:$$k!%(B
$B!!Nc$($P!$Nc(B4 $B$O(B timeout $B$N<BAu!J$N4JN,HG!K$G$9$,!$(Byield
$B$G5/F0$7$?%V(B
$B%m%C%/Cf$G!$(Bensure
$B$rMQ$$$F2?$+;q8;$N8e;OKv$r$7$F$$$?$H$7$F$b!$$=$N8e;O(B
$BKvCf$K!J(Bensure $B@a<B9TCf$K!K(BTimeoutError
$B$,H/@8$7$F$7$^$&2DG=@-$,$"$k!%(B
$BNc(B4
def timeout(sec)
timer_thread = Thread.new(Thread.current){|parent|
sleep(sec)
parent.raise(TimeoutError)
}
begin
yield
ensure
timer_thread.stop # close thread
end
end
timeout(3){
begin
f = open(…) # open(…){|f| …}
$B$G$$$$$s$@$1$I!$$^$!Nc$H$7$F(B
ensure
f.close
end
}
$B$G$O!$(Bensure
$B$@$1$G$$$$$N$+!$$H$$$&$H!$$=$l0J30$K$bLdBj$,$"$k!%Nc$($P(B
$B<!$K<($9Nc(B5$B$K$D$$$F9M$($k!%(B
$BNc(B5
begin
f = open(…)
ensure
f.close if f
end
$B!!(Bopen(…) $B$G3+$$$?$b$N$r!$(B"f ="
$B$G%m!<%+%kJQ?t$KBeF~$,40N;$9$kA0$K3d$j(B
$B9~$^$l$?$H$-!$(Bf $B$O(B nil $B$N$^$^$J$N$G(B ensure $B$G(B close
$B$5$l$J$$!%$3$NNc$N(B
File $B$N>l9g$O(B GC
$B$GJD$8$k$3$H$b2DG=$@$,!$2rJ|$rI,?$H$9$k;q8;0lHL$r9M$((B
$B$k$HLdBj$G$"$k!%(B
$B!!$3$NE@$K$D$$$F!$Nc$($P!$9TKv$^$G3d$j9~$_$r5v$5$J$$!J9TKv$@$1%A%'%C%/$9(B
$B$k!K!$$H$$$C$?2r7h0F$bDs0F$5$l$?$,!$(B"f =" $B$d(B “open(…)”
$B$,$b$C$HJ#;((B
$B$@$C$?>l9g!$$=$N2r7h$G$OL5M}$G$“$k!JNc$($P!$(B"foo.bar =”
$B$OJ#?t9T$N%a%=%C(B
$B%I$N>l9g$,$"$k!K!%(B
$BDs0F!'(B
$B!!HsF14|3d$j9~$$r%A%'%C%/$9$k%?%$%%s%0$r@)8f$9$k$?$a$N;EAH$$r?7@$9(B
$B$k!%860F$O(B [1] $B$K$"$k$H$*$j!%$?$@!$L>A0$K$D$$$F$O:#8e8!F$$9$k!%(B
$B!!@)8f$N<oN`$O<!$NDL$j!$(B
$B!!!(B0. $B$J$k$Y$/IQHK$K%A%‘%C%/$9$k!J$3$l$^$GDL$j$NF0:n!K(B
$B!!!(B1. $B%V%m%C%/(B I/O $B$N%?%$%_%s%0$@$1%A%’%C%/$9$k(B
2. $B%A%'%C%/$7$J$$(B
$B!!(B0 $B$O$3$l$^$GDL$j!%(B
$B!!(B1 $B$O!$(BPOSIX thread $B$N(B cancellation point
$B$i$7$$!%D9;~4V%V%m%C%/$9$k=h(B
$BM}$O(B Thread#raise $B$d%7%0%J%k$G%-%c%s%;%k$9$k$3$H$,2DG=!%(B
$B!!(B2
$B$O!$0l@Z%A%'%C%/$7$J$$!%40A4$KHsF14|3d$j9~$_%;!<%U$K=hM}$9$k$3$H$,2DG=!%(B
$B!!$?$@$7!%%A%‘%C%/$9$kNc30%/%i%9!J$NAD@h!K$O;XDj$G$-$k$h$&$K$9$k!%$3$l$K(B
$B$h$j!$Nc$($P(B SignalException $B!J$r7Q>5$7$?(B
Interrupt$B!K$OIQHK$K%A%’%C%/$9(B
$B$k!$$9$J$o$A(B Ctrl+C $B$O$@$$$?$$8z$/!$$7$+$7!$(BTimeoutError
$B$N$h$&$JNc30$O(B
$B0BA4$J$H$3$m$^$GCY1d$7$F=hM}$9$k$H$$$C$?5sF0$,MF0W$K5-=R$G$-$k!%(B
$B5DO@!'(B
$B!&%G%U%)%k%H$r$I$N%b!<%I!JA0@a(B 0$B!A(B2 $B$N$3$H!K$K$9$k$+!)(B
$B!!!&%b!<%I(B 1 $B$G:$$k?M$O$I$l$/$i$$$$$k$+!)(B
$B!!!J$$$J$$$J$i%G%U%)%k%H$3$l$G$$$$$s$G$O!)!K(B
$B!!!&7W;;%9%l%C%I$O;$a$F$b:$$i$J$$$N$G!$Nc(B2$B$N$h$&$J>l9g$O$3$l$^$G(B
$B!!!DL$j;$a$?$$!$$H$$$&!$%b!<%I(B 0 $B$r4|BT$9$kNc$O$"$k!%(B
$B!&(Bensure $B<B9T;~$K<+F0E*$K%b!<%I$rJQ99$9$k$+!)(B
$B"($($($H!$$9$_$^$;$s!$$$$m$s$J5DO@$,$"$C$?$H;W$$$^$7$?$,!$C/$+Jd40$7$F2<(B
$B$5$$(B…$B!%(B
$BM>CL!J$H$$$&$+(B TODO$B!K!'(B
$B!!(Brb_blocking_region() $B;~$K6/@)E*$K=*N;;~$K(B CHECK_INTS()
$B$7$F$$$k$N$O$1(B
$B$7$+$i$s$N$G!$(BCHECK_INTS()
$B$r8F$S=P$7B&$G$5$;$k%P!<%8%g%s$r:n$k$Y$-$G$"$k!%(B
$B!!Nc$($P!$(B
blocking_region{
data = read(…)
}
$B$H$“$C$?$H$-!$(Bdata
$B$,E~C#$7$F$$$k$N$J$i$P!$3d$j9~$s$GM_$7$/$J$$$O$:$G(B
$B$”$k!%$?$@$7!$(Bdata
$B$,E~C#$9$kA0$K3d$j9~$_$GCfCG$7$F$$$l$P!$(BCHECK_INTS()
$B$K$h$jNc30$rH/@8$5$;$k$Y$-$G$“$k!%$3$NH=CG$O(B rb_bocking_region()
$BMxMQ<T(B
$B$7$+$G$-$J$$$N$G!$$=$NH=CG$r$5$;$k$Y$-$G$”$k!%(B
$B;29MJ88%!'(B
[1] Akira T. “Re: Thread#raise, Thread#kill, and timeout.rb are
unsafe” ruty-talk (2008.3)
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/294917
$B<U<-!'(B
$B!!$3$N5DO@$O!$(B3/11
10:00$B$+$i3+:E$5$l$?(BRuby$B3+H/<T2q5D$G9T$o$l$^$7$?!%;22C(B
$B<T$OEDCf$5$s!$(Bnahi $B$5$s!$$?$k$$$5$s!$(Bmrkn $B$5$s!$(Bskype
$B1[$7$K>.:j$5$s!$Cf(B
$BED$5$s!$(Bsora
$B$5$s!$1sF#$5$s$G$7$?!%D+$b$O$h$+$i$"$j$,$H$&$4$6$$$^$7$?!%(B