非同期割り込みに対する対処案(日本語版)

$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

$B@P0f$H?=$7$^$9!#(B

$BK\F|!“ESCf!”(B11$B;~$+$i(B2$B;~4V$[$I!“;22C$5$;$F$$$?$@$-$^$7$?!#(B
$B8a8e$+$iB>$NMQ;v$,$”$C$?$N$G<:Ni$5$;$F$$$?$@$-$^$7$?!#(B
$BK\F|$O6=L#?<$$5DO@$rGR8+$5$;$F$$$?$@$-!“$”$j$,$H$&$4$6$$$^$9!#(B

$BIaCJ$O%G!<%?2r@O$K(BRuby $B$r4^$a$$$m$$$m$J8@8l$r;HMQ$7$F$$$^$9$,!"(B
$B8@8l$N<BAu$r4^$a3+H/$K$b6=L#$r;}$C$F$$$^$9!#(B

$B:#8e$H$b$h$m$7$/$*4j$$$$$?$7$^$9!#(B

12/03/11 SASADA Koichi [email protected]:

議論には参加していませんが、概要まで訳してみました。

How can asynchronous interrupt survive

Terms
trap handler: a block that should be executed when a signal registered
to trap
the content (…) of trap(SIGINT){…}

asynchronous interrupt: unintended event such as Thread#raise or trap
handler

意図しないってなんか変じゃありません?

Interrupt check: Determine if there is any asynchronous exception (未定義),
and raise an error or invoke trap handler if there is any exception.

Blocking procedure: a procedure that may be blocked including I/O

Summary
Ruby will provide a primitive to regulate the timing to check
for the asynchronous interrupt. Three kinds of regulation should be
provided
0. check as frequently as possible (this is the current behaviour)

  1. check at a blocking procedure.
  2. don’t check
    Note that the behaviour can be specified per exception class.
    Therefore, SignalException and its descendants are checked frequently.
    This enables to write a code that Ctrl-C cause interrupt but
    exceptions like TimeoutError are delayed to a safe point.

$B1sF#$G$9!#(B

2012-03-11 SASADA Koichi [email protected]:

$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

$B0l1~JdB-$7$^$9$H!"%V%m%C%/(B I/O $B$K8B$i$:%V%m%C%/$rH/@8$5$;$&$k(B
API
$B$OA4It%A%'%C%/$9$Y$-$@$H;W$$$^$9!#Nc$($P(B:

  • $BL@<(E*$J%&%'%$%H(B (Kernel#sleep)
  • $B>r7oJQ?tBT$A(B (ConditionVariable#wait)
  • $B%9%l%C%I=*N;BT$A(B (Thread#join)
  • $B%W%m%;%9=*N;BT$A(B (Kernel#system, Process#wait $B$J$I(B)

$BMW$9$k$K(B rb_thread_blocking_region $B$r8F$V$"$?$jA4It!#>/$J$/$H$b(B
POSIX thread $B$N(B cancellation point $B$O$=$&Dj5A$5$l$F$$$^$9!#(B

$B$b$C$H:Y$+$$$3$H$r8@$&$H!“(BPOSIX thread $B$G$O(B mutex
$B$N%m%C%/BT$A$O(B
$B%V%m%C%/$7$&$k$1$l$I(B cancellation point $B$K$J$C$F$$$^$;$s!#(B
$B$=$NM}M3$O!”?dB,$G$9$,(B

  • mutex $B$N%m%C%/$G3d$j$3$^$l$k$h$&$G$O%W%m%0%i%`$r=q$/$N$,Fq$7$$(B
  • cancellation point $B$K4X78$J$/!“(Bmutex
    $B$O%m%C%/Fb$N=hM}$r0l=V$G(B
    $B=*N;$9$k$3$H$,5a$a$i$l$F$$$F!”%m%C%/$G!V%V%m%C%/!W$9$k$[$IBT$D(B
    $B%1!<%9$OA[Dj$5$l$F$$$J$$(B

$B$J$I$+$H;W$$$^$9!#(B
$B$?$@$7(B Haskell $B$NHsF14|Nc30(B [2] $B$G$O(B mutex $B$N%m%C%/$b(B
cancellation
point ($BAjEv(B)
$B$K$J$C$F$*$j!“%G%U%!%/%H$N@_7W%]%j%7!<$,$”$k$o$1$G$O(B
$B$J$5$=$&$G$9!#(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

[2] Simon Marlow, Simon Peyton Jones, Andy Moran and John Reppy.
Asynchronous Exceptions in Haskell, in PLDI’01.

$B$?$k$$$G$9!#(B

$B0lE@$@$1DI2C$G$9!#(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

$BHsF14|3d$j9~$$r%A%'%C%/$9$k%?%$%%s%0$r8:$i$9$N$GBe$o$j$KL@<(E*$K%A%‘%C%/$9$k(B
primitive$B$bF3F~$7$h$&$H$$$&OC$J$C$F$$$?$H;W$$$^$9!#(B
$B$=$N%A%’%C%/$9$k(Bprimitive$B$G!"HsF14|Nc30$K$D$$$FNc30$,Mh$F$$$?>l9g$K%A%‘%C%/$7$F(B
$BNc30$r=P$9$N$+!"Nc30%*%V%8%’%/%H$rJV$9$N$+$O5DO@$,J,$+$l$F$$$^$7$?!#(B

2012$BG/(B3$B7n(B11$BF|(B20:35 SASADA Koichi [email protected]:

On 2012$BG/(B03$B7n(B12$BF|(B 21:00, Yusuke E. wrote:

$B$b$C$H:Y$+$$$3$H$r8@$&$H!"(BPOSIX thread $B$G$O(B mutex $B$N%m%C%/BT$A$O(B
$B%V%m%C%/$7$&$k$1$l$I(B cancellation point $B$K$J$C$F$$$^$;$s!#(B
$B$=$NM}M3$O!"?dB,$G$9$,(B

  • mutex $B$N%m%C%/$G3d$j$3$^$l$k$h$&$G$O%W%m%0%i%`$r=q$/$N$,Fq$7$$(B
  • cancellation point $B$K4X78$J$/!"(Bmutex $B$O%m%C%/Fb$N=hM}$r0l=V$G(B
    $B=*N;$9$k$3$H$,5a$a$i$l$F$$$F!"%m%C%/$G!V%V%m%C%/!W$9$k$[$IBT$D(B
    $B%1!<%9$OA[Dj$5$l$F$$$J$$(B

$B$J$I$+$H;W$$$^$9!#(B

POSIX$B$G$O%-%c%s%;%k$,5/$3$k$H$?$@=hM}$,CfCG$5$l$k$N$G$O$J$/%/%j!<%s%"%C%W(B
$B%O%s%I%i$,F0$/$3$H$,$"$j$^$9!#$3$3$G!">r7oJQ?t$rBT$C$F$$$k%9%l%C%I$,%-%c%s(B
$B%;%k$5$l$?;~$K%/%j!<%s%"%C%W%O%s%I%i$KFMF~$9$k$H!"$=$N%O%s%I%iFb$G>r7oJQ?t(B
$B$,BT$C$F$$$?(Bmuetx$B$O%m%C%/$5$l$?>uBV$GFMF~$7$F$/$k$3$H$K$J$C$F$$$^$9!#$7$?(B
$B$,$C$F%/%j!<%s%"%C%W%O%s%I%i$O>o$K(Bmutex$B$r%m%C%/$7$F$$$kA0Ds$G=q$$$F$h$$$3(B
$B$H$K$J$C$F$$$^$9!#$H$3$m$,(Bmutex$B$N%-%c%s%;%k$,(BOK$B$H$$$&$3$H$K$9$k$H!"%/%j!<(B
$B%s%"%C%W%O%s%I%i$O(Bmutex$B$,%m%C%/$5$l$F$$$k$N$+!"%m%C%/$5$l$F$$$J$$$N$+$h$/(B
$B$o$+$i$J$$$h$&$J46$8$GF0$/$H$$$&$3$H$K$J$j$^$9!#$3$l$O@5$7$/=q$/$N$,$H$F$b(B
$BLLE]$G$9!#(B

$B$H$$$C$?$3$H$,(Bpthread_cond_wait(3posix)$B$N(BRATIONALE$B$K=q$$$F$"$j$^$9!#(B

$B1sF#$G$9!#(B

2012-03-13 Urabe S. [email protected]:

$B$J$I$+$H;W$$$^$9!#(B

$B$H$$$C$?$3$H$,(Bpthread_cond_wait(3posix)$B$N(BRATIONALE$B$K=q$$$F$"$j$^$9!#(B

$B$X!<!#$3$l$OCN$j$^$;$s$G$7$?!#(B
POSIX thread $B$r??;w$9$k$J$i5$$r$D$1$?J}$,$$$$$G$9$M!#(B

$B$?$@!“;d$,8@$C$?$N$O!V(Bpthread_mutex_lock $B$O%V%m%C%/$7$&$k$1$I(B
cancellation point $B$8$c$J$$!W$H$$$&OC$G!”>e$H$OJL$NOC$G$9!#(B

http://pubs.opengroup.org/onlinepubs/007904875/functions/pthread_mutex_lock.html

$B$O8+$?$s$G$9$,!"FC$K(B rationale
$B$O=q$$$F$J$$$h$&$G$7$?!#8!:w$7$F$_$?$i(B

http://www.mkssoftware.com/docs/man3/pthread_cancel.3.asp

pthread_mutex_lock() is not a cancellation point, although it may
block indefinitely; making pthread_mutex_lock() a cancellation point
would make writing correct cancellation handlers difficult, if not
impossible.

http://sourceware.org/pthreads-win32/manual/pthread_mutex_init.html

None of the mutex functions is a cancellation point, not even
pthread_mutex_lock, in spite of the fact that it can suspend a thread
for arbitrary durations. This way, the status of mutexes at
cancellation points is predictable, allowing cancellation handlers to
unlock precisely those mutexes that need to be unlocked before the
thread stops executing. Consequently, threads using deferred
cancellation should never hold a mutex for extended periods of time.

$B$J$I!"$d$O$j!V%W%m%0%i%`$r=q$/$N$,Fq$7$/$J$j$9$.$k$+$i!W$H$$$&$3$H$N(B
$B$h$&$G$9!#(B

$B$$$:$l$K$;$h!"$+$J$jM>CL$K6a$$OC$G$9!#$9$_$^$;$s!#(B

$B!!$5$5$@$G$9!%(B

(2012/03/11 20:35), SASADA Koichi wrote:

$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

$B!!$3$A$i!$$9$C$+$jJ|CV$7$F$$$?$s$G$9$,!$$J$s$H$+$7$J$$$H$H;W$C$F(B
reboot
$B$7$^$9!%$9$$^$;$s!%;XE&$5$l$F$$$kE@$r<h$j9~$$^$7$?!%(B

$BEDCf$5$s!'(B[ruby-talk:294917] $B$GDs0F$5$l$F$$$?(B API
$B$K$D$$$F!$2<5-$K5?Ld$r(B
$B=q$$$F$$$^$9!%$9$_$^$;$s$,65$($FLc$($^$;$s$+!%(B

$B>.:j$5$s!'$J$s$+FM$C9~$_$"$j$^$9$+!%(B

$B$=$NB>!$FM$C9~$_4?7^$7$^$9!%7k6I!$%G%U%)%k%H$O$I$&$9$k$Y$-$J$s$@!%(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!%$J$N(B
$B$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

$B!!$^$?!$(B1, 2
$B$N>l9g$K!$%f!<%6$K$h$C$F6/@)E*$K$I$N$h$&$JNc30$,Mh$F$$$k$+(B
$B%A%'%C%/$G$-$k;EAH$_$rF3F~$9$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$$$F!$HsF14|(B
$B$K8F$P$l$k%V%m%C%/$r;XDj$9$k$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$@$,!$(Byield
$B$G5/F0$7$?%V%m%C(B
$B%/Cf$G!$(Bensure
$B$rMQ$$$F2?$+;q8;$N8e;OKv$r$7$F$$$?$H$7$F$b!$$=$N8e;OKvCf(B
$B$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$H$7$FDj5A$5$l$F$$$k2DG=@-$,$"$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%-%s%0=hM}$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$r;29M$K$7$F$$$k!%D9;~4V%V(B
$B%m%C%/$9$k=hM}$O(B Thread#raise
$B$d%7%0%J%k$G%-%c%s%;%k$9$k$3$H$,2DG=!%(B

$B!!(BI/O $B0J30$K$b(B

  • $BL@<(E*$J%&%'%$%H(B (Kernel#sleep)
  • $B>r7oJQ?tBT$A(B (ConditionVariable#wait)
  • $B%9%l%C%I=*N;BT$A(B (Thread#join)
  • $B%W%m%;%9=*N;BT$A(B (Kernel#system, Process#wait $B$J$I(B)

$B$J$I$,4^$^$l$k!%(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!&%f!<%6$K$h$C$FNc30$r(B poll $B$9$k=hM}$O!$Nc30$rH/@8$9$k$+!$(B
$B!!$=$l$H$bNc30%*%V%8%'%/%H$r<hF@$G$-$k$h$&$K$9$k$@$1$K$9$k$+!)(B

$B!&%b!<%I$rJQ99$9$k(B API $B$r$I$N$h$&$K@_7W$9$k$Y$-$+!)(B
$B!!(B[1] $B$G$O!$<!$NMM$J(B API $B$rDs0F$7$F$$$k!%(B

  • Thread.check_interrupt(klass)
  • Thread.blocking_interruptible(klass) { … }
  • Thread.blocking_uninterruptible(klass) { … }
  • Thread.delay_interrupt(klass) { … }

$B$,!$$3$N(B API $B$O!$HsF14|3d$j9~$_$r>o$K%A%'%C%/$9$k%b!<%I(B 0
$B$O5$$K$7$F$$$J(B
$B$$5$$,$9$k!%$"$H!$(Bdelay_interrupt $B$C$F$J$s$@$C$1!)(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
$B!!$=$N8e!$FM$C9~$_$r<u$1$?FbMF$rF~$l$^$7$?!%(B

2012$BG/(B6$B7n(B25$BF|(B 18:26 SASADA Koichi [email protected]:

$BEDCf$5$s!'(B[ruby-talk:294917] $B$GDs0F$5$l$F$$$?(B API
$B$K$D$$$F!$2<5-$K5?Ld$r(B
$B=q$$$F$$$^$9!%$9$_$^$;$s$,65$($FLc$($^$;$s$+!%(B

$B5?Ld$H$$$&$N$O$3$l$G$9$+$M!#(B

$B$"$H!$(Bdelay_interrupt $B$C$F$J$s$@$C$1!)(B

$B3P$($?$^$;$s$G$7$?$,!"FI$D>$9$H!"%V%m%C%-%s%0A`:n0J30$N(B
($BG$0U$N(B) $B>l=j$K$D$$$F(B
$B3d$j9~$
$rNc30$H$7$FH/@8$5$;$F$h$$$+$r@)8f$9$k%a%=%C%I$G$9$M!#(B

$B%V%m%C%/$NCf$OCY1d$5$;$k$H$$$&0U?^$G$9!#(B

$B!!$5$5$@$G$9!%(B

$B!!AaB.!$$"$j$,$H$&$4$6$$$^$9!%$?$@!$<ALd$N;EJ}$,0-$+$C$?$N$G!$<ALd$@$1JB(B
$B$Y$F$_$^$7$?!%(B

(2012/06/25 19:05), Tanaka A. wrote:

$B$"$H!$(Bdelay_interrupt $B$C$F$J$s$@$C$1!)(B
$B3P$($?$^$;$s$G$7$?$,!"FI$D>$9$H!"%V%m%C%-%s%0A`:n0J30$N(B ($BG$0U$N(B)
$B>l=j$K$D$$$F(B
$B3d$j9~$
$rNc30$H$7$FH/@8$5$;$F$h$$$+$r@)8f$9$k%a%=%C%I$G$9$M!#(B

$B%V%m%C%/$NCf$OCY1d$5$;$k$H$$$&0U?^$G$9!#(B

$B!!$H$$$&$o$1$G!$$o$+$j$E$i$+$C$?$N$G!$EDCf$5$s08$N5?Ld$rNs5s$7$^$9!%(B

(1) $B7k6I!$%G%U%)%k%H$N5sF0$O$I$&$9$k$Y$-$+!)(B

(2) Thread.delay_interrupt
$B$r8F$VA0$H!$8F$s$@8e$N%V%m%C%/$NCf$G$O$I$N$h(B
$B$&$K5sF0$OJQ2=$9$k$+!)(B

(3) Thread.blocking_interruptible()
$B$r8F$VA0$H!$8F$s$@8e$N%V%m%C%/$NCf$G(B
$B$O$I$N$h$&$K5sF0$OJQ2=$9$k$+!)(B

(4) Thread.blocking_uninterruptible()
$B$r8F$VA0$H!$8F$s$@8e$N%V%m%C%/$NCf(B
$B$G$O$I$N$h$&$K5sF0$OJQ2=$9$k$+!)(B

$B;d$N?dB,!&0U8+$G$9!’(B
(1) $B$K$D$$$F$OFC$K5,Dj$7$F$$$J$$5$$,$7$^$9!%4V0c$C$F$?$i$9$_$^$;$s!%(B
(2)
$B$O!$>e5-$N@bL@$H%a%=%C%IL>$+$i$I$C$A$,$I$C$A$@$+$o$+$j$^$;$s$G$7$?!%(B
(3) $B$O(B $B%b!<%I(B1, 2 -> $B%b!<%I(B2 $B$X$N@)8f$r9T$&!)(B
(4) $B$O(B $B%b!<%I(B0, 1 -> $B%b!<%I(B2 $B$X$N@)8f$r9T$&!)(B
(3, 4) $B$,$"$l$P!$(B (2) $B$OITMW$8$c$J$$$+!)(B

$B!!$"$H!$$h$/$h$/9M$($k$H!$(BThread.blocking_uninterruptible
$B$J$I$G!$(Bklass
$B$N;XDj$,(B n $B8D%M%9%H$9$k$H!$HsF14|3d$j9~$_$,5/$3$kEY$K(B n
$B2s%A%’%C%/$9$kI,(B
$BMW$,$"$k5$$,$7$^$9!%Jq4^4X78$,$"$k$N$G!$C1=c$K$=$&$G$O$J$$$s$G$9$,!%7Q>5(B
$B4X78$r9M$($k$H!$%O%C%7%e$G(B
O(1)$B!$$H$$$&$o$1$K$b$$$+$J$$!JHt$s$G$-$?Nc30(B
$B%*%V%8%’%/%H$N7Q>5LZ$N9b$5$,(B m $B8D$N>l9g!$(BO(m) $B$G$$$1$k$+!K!%(B

$B!!$^$?!$(B[ruby-talk:294917]
$B$G$O%-%e!<$G4IM}$9$k$Y$-!$$H$$$&$3$H$G$7$?(B
$B$,!$<oN`$K$h$C$F3d$j9~$_$,DI$$1[$92DG=@-$,$"$j$^$9!JNc$($P!$(BTimeoutError
$B$,%V%m%C%/$5$l$F$*$j!$%-%e!<$KCy$^$C$F$$$k$H$-!$(BInterruptError
$B$,Mh$?$i(B
$B$I$&$J$k$+!K!%(B

$B!!$3$N(B2$BE@$K$D$$$F!$9M$($r$*J9$+$;2<$5$$!%(B

(5) $B%A%’%C%/$N%3%9%H$r$I$&9M$($k$+!J(BO(m) $B$O4E<u$9$Y$-%3%9%H$+!K(B
(6) $BDI$$1[$7$,H/@8$9$k$H$-!$$I$&$9$k$HNI$$$+(B

$B!!$b$7!$5DO@$r8+F($7$F$$$?$i$9$_$^$;$s!%DI$$1[$7$N7o$O!$$J$s$+0JA0J9$$$?(B
$B$3$H$,$"$k$h$&$J5$$,$7$?$N$G$9$,!$K:$l$F$7$^$$$^$7$?!%(B

$B!!$"$H!$(B[ruby-talk:294917] $B$G$O(B “It is because
Thread.check_interrupt
with blocking operations causes race conditions.” $B$H!$(Brace
$B$,5/$3$k$H$+(B
$B$$$F$"$k$s$G$9$,!$$3$l$I$&$$$&OC$G$7$?$C$1!%(B

$B!!$5$5$@$G$9!%(B

$B!!AaB.$N2sEz!$$"$j$,$H$&$4$6$$$^$9!%(B

$B!!(B(1) $B$O%3%a%s%H$H$7$F=q$$$F$*$3$&!%(B

(2012/06/25 20:32), Tanaka A. wrote:

$B%V%m%C%/$9$kA`:n$d$=$l0J30$N>l=j$r(B safe point
$B$H$9$k$+$I$&$+$r@)8f$9$k46$8$K(B
$B$@$C$?$h$&$K;W$$$^$9!#(B

$B!!$=$l0J30$N>l=j$r(B safe point $B$K$9$k(B API
$B$,ITB-$7$F$$$k$G$7$g$&$+!)!J;d(B
$B$N8+Mn$H$7!)!K(B

$B!!6qBNE*$K$O!$(BThread.delay_interrupt $B$N5U!%(B

$B$,%V%m%C%/$5$l$F$*$j!$%-%e!<$KCy$^$C$F$$$k$H$-!$(BInterruptError $B$,Mh$?$i(B
$B$I$&$J$k$+!K!%(B

$BDI$$1[$9$N$G$O$J$$$+$H;W$$$^$9!#(B

(5) $B%A%’%C%/$N%3%9%H$r$I$&9M$($k$+!J(BO(m) $B$O4E<u$9$Y$-%3%9%H$+!K(B

$BHsF14|%$%Y%s%H$O$=$N%3%9%H$,LdBj$K$J$k$[$IIQHK$K;H$&$Y$-$b$N$G$O$J$$$s$8$c$J$$$G$7$g$&$+!#(B

$B86B’E*$K$O!"%W%m%;%9$N=*N;$N$?$a$K$N$_;H$&$Y$-$@$H;W$C$F$$$^$9!"(B

$B!!$D$^$j!$$3$N%-%e!<$OKX$I$N>l9g6u$G$"$k$?$a!$$b$7$/$O6u$K$9$k$Y$-$G$"$k(B
$B$?$a!$%3%9%H$K4X$7$F$O$"$^$j5$$K$J$i$J$$$s$8$c$J$$$N!$$H$$$&$3$H$G$9$M!%(B

(6) $BDI$$1[$7$,H/@8$9$k$H$-!$$I$&$9$k$HNI$$$+(B

$BDI$$1[$;$P$$$$$s$8$c$J$$$G$7$g$&$+!#(B
$B$J$K$rLdBj$H46$8$F$$$k$N$+$o$+$j$^$;$s!#(B

$B!!2?$+$NCF$_$G%-%e!<$KNc30$,5M$^$C$F$-$?$H$-!$%J%$!<%V$K:n$k$H$+$J$j%*!<(B
$B%P%X%C%I$,$+$+$j$=$&$@$J$!!$$H;W$C$?$s$G$9$,!$5$9g$$F~$l$F7k2L$r$-$A$s$H(B
$B%-%c%C%7%e$9$l$P$J$s$H$+$J$k$+$J(B…$B!%(B

$B!!$"$H!$(B[ruby-talk:294917] $B$G$O(B “It is because Thread.check_interrupt
with blocking operations causes race conditions.” $B$H!$(Brace $B$,5/$3$k$H$+(B
$B$$$F$"$k$s$G$9$,!$$3$l$I$&$$$&OC$G$7$?$C$1!%(B

$B$"$!!"(Brace $B$b$"$j$^$9$,!"$b$C$H$"$+$i$5$^$K%V%m%C%/$7$F$$$k:GCf$K(B
$BCfCG$G$-$J$1$l$P$J$i$J$$$H$$$&$[$&$,$o$+$j$d$9$$I,MW@-$+$b$7$l$^$;$s!#(B

race $B$O!"%V%m%C%/$9$kD>A0$dD>8e$K%7%0%J%k$,Mh$?$H$-$NOC$rA[Dj$7$F$$$^$7$?!#(B
$B$b$7(B Binary Hacks
$B$r;}$C$F$$$k$J$i!V(Bsigsafe$B$G%7%0%J%k=hM}$r0BA4$K$9$k!W$H$$$&(B
$B$N$rFI$s$G$_$F$/$@$5$$!#(B

$B!!$J$k$[$I!$$=$NOC$G$7$?$+!%N;2r$G$9!%(B

2012$BG/(B6$B7n(B25$BF|(B 21:01 SASADA Koichi [email protected]:

$B!!$=$l0J30$N>l=j$r(B safe point $B$K$9$k(B API
$B$,ITB-$7$F$$$k$G$7$g$&$+!)!J;d(B
$B$N8+Mn$H$7!)!K(B

$B!!6qBNE*$K$O!$(BThread.delay_interrupt $B$N5U!%(B

$B$"$C$?$[$&$,E,@Z$+$b$7$l$^$;$s$M!#(B

2012$BG/(B6$B7n(B25$BF|(B 19:39 SASADA Koichi [email protected]:

(1) $B7k6I!$%G%U%)%k%H$N5sF0$O$I$&$9$k$Y$-$+!)(B

$B$^$:!“(BSIGINT (^C) $B$G(B ruby
$B$r=*N;$G$-$k$3$H$O$H$F$b=EMW$G$9$+$i!”(B
$B$3$l$K$D$$$F$OB(:B$KNc30$K$J$k$Y$-$G$7$g$&!#(B

SIGTERM $B$J$IB>$N%7%0%J%k$bF1MM$@$H;W$$$^$9!#(B

$B$=$l0J30$K$D$$$F$O!“(B100% $B%3%s%Q%A%V%k$H$$$&OC$rB:=E$9$k$J$i!”(B
$B$d$O$j$=$l$b8=>u$I$$jB(:B$KNc30$J$s$8$c$J$$$G$7$g$&$+!#(B
$BB:=E$7$J$$$J$i!"CY1d$5$;$k$H$$$&A
Br;h$b$"$k$+$b$7$l$^$;$s!#(B

(2) Thread.delay_interrupt $B$r8F$VA0$H!$8F$s$@8e$N%V%m%C%/$NCf$G$O$I$N$h(B
$B$&$K5sF0$OJQ2=$9$k$+!)(B

$B%V%m%C%/$NFbB&$G$OHsF14|%$%Y%s%H$KBP$9$kNc30$O(B safe point
$B$^$GCY1d$7$^$9!#(B

$B30B&$K$D$$$F$O!"$5$i$K30B&$G(B Thread.delay_interrupt
$B$G3g$i$l$F$$$k$+$I$&$+$K(B
$B0MB8$7$^$9!#(B

(3) Thread.blocking_interruptible() $B$r8F$VA0$H!$8F$s$@8e$N%V%m%C%/$NCf$G(B
$B$O$I$N$h$&$K5sF0$OJQ2=$9$k$+!)(B

$B%V%m%C%/$NFbB&$K$D$$$F$O!"%V%m%C%-%s%0A`:n$,(B safe point
$B$K$J$j$^$9!#(B

$B30B&$K$D$$$F$O!"$5$i$K30B&$G(B Thread.blocking_interruptible $B$d(B
Thread.blocking_uninterruptible $B$G3g$i$l$F$$$k$+$I$&$+$K0MB8$7$^$9!#(B

(4) Thread.blocking_uninterruptible() $B$r8F$VA0$H!$8F$s$@8e$N%V%m%C%/$NCf(B
$B$G$O$I$N$h$&$K5sF0$OJQ2=$9$k$+!)(B

$B%V%m%C%/$NFbB&$K$D$$$F$O!"%V%m%C%-%s%0A`:n$,(B safe point
$B$G$J$/$J$j$^$9!#(B

$B30B&$K$D$$$F$O!"$5$i$K30B&$G(B Thread.blocking_interruptible $B$d(B
Thread.blocking_uninterruptible $B$G3g$i$l$F$$$k$+$I$&$+$K0MB8$7$^$9!#(B

$B;d$N?dB,!&0U8+$G$9!'(B
(1) $B$K$D$$$F$OFC$K5,Dj$7$F$$$J$$5$$,$7$^$9!%4V0c$C$F$?$i$9$_$^$;$s!%(B
(2) $B$O!$>e5-$N@bL@$H%a%=%C%IL>$+$i$I$C$A$,$I$C$A$@$+$o$+$j$^$;$s$G$7$?!%(B
(3) $B$O(B $B%b!<%I(B1, 2 → $B%b!<%I(B2 $B$X$N@)8f$r9T$&!)(B
(4) $B$O(B $B%b!<%I(B0, 1 → $B%b!<%I(B2 $B$X$N@)8f$r9T$&!)(B
(3, 4) $B$,$"$l$P!$(B (2) $B$OITMW$8$c$J$$$+!)(B

$B;d$,=q$$$?;~E@$G$O%b!<%I(B 0, 1, 2
$B$H$$$&9M$(J}$G$O$J$+$C$?$N$G$7$g$&!#(B

$B%V%m%C%/$9$kA`:n$d$=$l0J30$N>l=j$r(B safe point
$B$H$9$k$+$I$&$+$r@)8f$9$k46$8$K(B
$B$@$C$?$h$&$K;W$$$^$9!#(B

$B!!$“$H!$$h$/$h$/9M$($k$H!$(BThread.blocking_uninterruptible $B$J$I$G!$(Bklass
$B$N;XDj$,(B n $B8D%M%9%H$9$k$H!$HsF14|3d$j9~$_$,5/$3$kEY$K(B n
$B2s%A%'%C%/$9$kI,(B
$BMW$,$”$k5$$,$7$^$9!%Jq4^4X78$,$"$k$N$G!$C1=c$K$=$&$G$O$J$$$s$G$9$,!%7Q>5(B
$B4X78$r9M$($k$H!$%O%C%7%e$G(B O(1)$B!$$H$$$&$o$1$K$b$$$+$J$$!JHt$s$G$-$?Nc30(B
$B%*%V%8%'%/%H$N7Q>5LZ$N9b$5$,(B m $B8D$N>l9g!$(BO(m) $B$G$$$1$k$+!K!%(B

$B$=$&$G$9$M!#(B

$B!!$^$?!$(B[ruby-talk:294917] $B$G$O%-%e!<$G4IM}$9$k$Y$-!$$H$$$&$3$H$G$7$?(B
$B$,!$<oN`$K$h$C$F3d$j9~$_$,DI$$1[$92DG=@-$,$"$j$^$9!JNc$($P!$(BTimeoutError
$B$,%V%m%C%/$5$l$F$*$j!$%-%e!<$KCy$^$C$F$$$k$H$-!$(BInterruptError $B$,Mh$?$i(B
$B$I$&$J$k$+!K!%(B

$BDI$$1[$9$N$G$O$J$$$+$H;W$$$^$9!#(B

(5) $B%A%'%C%/$N%3%9%H$r$I$&9M$($k$+!J(BO(m) $B$O4E<u$9$Y$-%3%9%H$+!K(B

$BHsF14|%$%Y%s%H$O$=$N%3%9%H$,LdBj$K$J$k$[$IIQHK$K;H$&$Y$-$b$N$G$O$J$$$s$8$c$J$$$G$7$g$&$+!#(B

$B86B’E*$K$O!“%W%m%;%9$N=*N;$N$?$a$K$N$_;H$&$Y$-$@$H;W$C$F$$$^$9!”(B

(6) $BDI$$1[$7$,H/@8$9$k$H$-!$$I$&$9$k$HNI$$$+(B

$BDI$$1[$;$P$$$$$s$8$c$J$$$G$7$g$&$+!#(B
$B$J$K$rLdBj$H46$8$F$$$k$N$+$o$+$j$^$;$s!#(B

$B!!$“$H!$(B[ruby-talk:294917] $B$G$O(B “It is because Thread.check_interrupt
with blocking operations causes race conditions.” $B$H!$(Brace $B$,5/$3$k$H$+(B
$B$$$F$”$k$s$G$9$,!$$3$l$I$&$$$&OC$G$7$?$C$1!%(B

$B$“$!!”(Brace
$B$b$“$j$^$9$,!”$b$C$H$"$+$i$5$^$K%V%m%C%/$7$F$$$k:GCf$K(B
$BCfCG$G$-$J$1$l$P$J$i$J$$$H$$$&$[$&$,$o$+$j$d$9$$I,MW@-$+$b$7$l$^$;$s!#(B

race
$B$O!"%V%m%C%/$9$kD>A0$dD>8e$K%7%0%J%k$,Mh$?$H$-$NOC$rA[Dj$7$F$$$^$7$?!#(B
$B$b$7(B Binary Hacks
$B$r;}$C$F$$$k$J$i!V(Bsigsafe$B$G%7%0%J%k=hM}$r0BA4$K$9$k!W$H$$$&(B
$B$N$rFI$s$G$_$F$/$@$5$$!#(B

$B$N#3$D$K$J$k$h$&$J5$$,$7$F$$$^$9$N$G!$$"$kNc30$,$3$l$i(B 3 $B$D$N$I$N>uBV$K(B
$B$9$k$+!$$H$$$&(B API $B$r9M$($F$_$^$7$?!%(B

(a) Thread.interrupt_mask(exception, state) do; end
(b) Thread.interrupt_mask(hash) do; end

(b)$B$N$[$&$O;XDj$7$?A4$F$NJQ99$,%"%H%_%C%/$K@Z$jBX$o$i$J$$$H@dBPJ86g$,=P$k(BAPI$B$@$H;W$&$N$G$9$,!"$O$?$7$F$=$s$J$3$H$,2DG=$G$7$g$&$+(B

$B$^$?!"(Bblocking_interruptible$B$N$H$-$,!"(Bpthread cancel
$B%b%G%k$J$N$G$"$l$P!"(B
$B<+H/E*$KNc30$r3NG’$9$k(B pthread cancel()
$B4X?tAjEv$N%a%=%C%I$,I,MW$@$H;W$$$^$9(B

:immediate_interruptible
:blocking_interruptible
:uninterruptible

$B%a%=%C%IL>$H0z?t$NN>J}$K(B
interrupt$B$NC18l$,F~$C$F$$$k$N$O$d$d>iD9$G$O$J$$$G$7$g$&$+(B

(1) $B%7%0%J%k$r5v$9$H8@$C$F$b!$(BSIGUSR1 $B$H$+$b5v$7$F$$$$$N$+$J!%(B

$B%7%0%J%kKh$K0c$&(BException$B$rEj$2$k$Y$-$@$H;W$$$^$9!#A4It(BSignalException$B$N(B
$B%5%V%/%i%9$K$9$l$P4{B8$N%3!<%I$GF0$/$s$8$c$J$$$G$7$g$&$+(B

(2) POSIX $B$_$?$$$K!$$3$N%a%=%C%I$O(B blocking $B$H$+!$$9$Y$F$-$A$s$H(B
$B=q$-O"$M$kI,MW$,$"$k$N$+$J!%$+$J$j!$L5M}$J5$$,$9$k(B
$B!!!J$=$b$=$b!$2?$,$I$N%a%=%C%I$r8F$S=P$9$+$o$+$i$J$$5$$,!K!%(B

$BEvLL(BGVL$BN%$9$H$3$m$G!"%A%’%C%/$9$k$h$&$K$7$F!"(BGVL$BN%$9%?%$%_%s%0$r(B
$B=y!9$KA}$d$7$F$$$/$H$+$G$9$+$M!#(B

(3) $B%i%$%V%i%j$N;j$k=j$G$3$s$J$N=q$+$l$?$i%O%C%7%e$,BgNLH/@8$7$F!$(B
$B%*!<%P%X%C%I$GBgJQ$K$J$C$?$j$7$J$$$@$m$&$+(B…$B!%(B
$B$=$b$=$b!$$3$l$C$FB?MQ$9$k$s$@$m$&$+!%(B

$B$o$?$7$NA[Dj$O!"#19TL$G(B blocking_interruptible
$B$K$7$FFsEY$HJQ$($J$$!#(B
ensure$B$NCf$G(BIO$B$r8F$V$H$-$@$10l;~E*$K(B uninterruptible$B$KJQ99(B

(4) $B%V%m%C%/$r;}$?$J$$(B Thread.mask_interrupt() $B$O5v$9$Y$-$@$m$&$+!%(B
$B!!!J0UL#$H$7$F$O!$!V$3$N8F$S=P$70J9_$O$3$N@_Dj$G!W!$$H$$$&46$8!K(B
$B$J$s$H$J$/!$5v$5$J$$J}$,$$$$$h$&$J5$$,$9$k$s$@$1$I(B

(3)$B$H$"$o$;$F%V%m%C%/I,?$@$HA4%W%m%0%i%`$,0lCJ%M%9%H$,?<$/$J$k$N$G(B
$B$&$l$7$/$J$$$J$"(B

(5) Thread.mask_interrupt() $B$O%M%9%H$7$?$i@_Dj$r:.$<$F$$$/!$$H$7$?$1$I(B
$BC1$K!$CV$-49$($k!$$H$$$&A*Br;h$b$"$k$N$+!%$3$C$A$N$[$&$,;H$$$d$9$$!)(B

$B:.$<$F$$$/!#$H$$$&$N$,$J$K$r;X$7$F$$$k$N$+<h$l$J$+$C$?$N$GCV$-49$($k%b%G%k$GF0:nNc$r=q$$$F$$$?$@$1$k$H$&$l$7$$$G$9(B

(2012/06/26 4:44), KOSAKI Motohiro wrote:

$B$N#3$D$K$J$k$h$&$J5$$,$7$F$$$^$9$N$G!$$"$kNc30$,$3$l$i(B 3 $B$D$N$I$N>uBV$K(B
$B$9$k$+!$$H$$$&(B API $B$r9M$($F$_$^$7$?!%(B

(a) Thread.interrupt_mask(exception, state) do; end
(b) Thread.interrupt_mask(hash) do; end

(b)$B$N$[$&$O;XDj$7$?A4$F$NJQ99$,%"%H%_%C%/$K@Z$jBX$o$i$J$$$H@dBPJ86g$,=P$k(BAPI$B$@$H;W$&$N$G$9$,!"$O$?$7$F$=$s$J$3$H$,2DG=$G$7$g$&$+(B

$B!!(BC $B$G=q$/(B API $B$@$+$i!$(Batomic $B$KJQ$o$j$^$9!%(B

$B$^$?!"(Bblocking_interruptible$B$N$H$-$,!"(Bpthread cancel
$B%b%G%k$J$N$G$"$l$P!"(B
$B<+H/E*$KNc30$r3NG’$9$k(B pthread cancel()
$B4X?tAjEv$N%a%=%C%I$,I,MW$@$H;W$$$^$9(B

$B!!$=$l$rK:$l$F$$$^$7$?!%MW$9$k$KNc30$,FO$$$F$$$k$+%A%’%C%/$9$k%a%=%C%I$G(B
$B$9$h$M!%(BThread.check_ints()
$B$H$7$F$*$3$&!JL>A0$O$H$j$"$($:E,Ev$G$9!K!%(B

:immediate_interruptible
:blocking_interruptible
:uninterruptible

$B%a%=%C%IL>$H0z?t$NN>J}$K(B
interrupt$B$NC18l$,F~$C$F$$$k$N$O$d$d>iD9$G$O$J$$$G$7$g$&$+(B

$B!!>iD9$@$H$$$&$N$KF10U$7$^$9!%$,!$$H$j$"$($:5sF0$r5DO@$7$?$$$N$G!$$=$N$^(B
$B$^$G!%L>A0$O$b$&$A$g$C$H8e$G!%(B

(1) $B%7%0%J%k$r5v$9$H8@$C$F$b!$(BSIGUSR1 $B$H$+$b5v$7$F$$$$$N$+$J!%(B

$B%7%0%J%kKh$K0c$&(BException$B$rEj$2$k$Y$-$@$H;W$$$^$9!#A4It(BSignalException$B$N(B

$B%5%V%/%i%9$K$9$l$P4{B8$N%3!<%I$GF0$/$s$8$c$J$$$G$7$g$&$+(B

$B!!$3$l$O!$$A$g$C$H(B off topic $B$G$9$+$M!%(B

(2) POSIX $B$_$?$$$K!$$3$N%a%=%C%I$O(B blocking $B$H$+!$$9$Y$F$-$A$s$H(B
$B=q$-O"$M$kI,MW$,$"$k$N$+$J!%$+$J$j!$L5M}$J5$$,$9$k(B
$B!!!J$=$b$=$b!$2?$,$I$N%a%=%C%I$r8F$S=P$9$+$o$+$i$J$$5$$,!K!%(B

$BEvLL(BGVL$BN%$9$H$3$m$G!"%A%’%C%/$9$k$h$&$K$7$F!"(BGVL$BN%$9%?%$%_%s%0$r(B
$B=y!9$KA}$d$7$F$$$/$H$+$G$9$+$M!#(B

$B!!$3$3$O!$%I%-%e%a%s%H$NOC$r$7$F$$$?$D$b$j$G$9!%(B

$B!!A}$d$7$F$$$/$H4r$7$$$3$H$,$"$k!)(B

$B$J$s$H$J$/!$5v$5$J$$J}$,$$$$$h$&$J5$$,$9$k$s$@$1$I(B

(3)$B$H$"$o$;$F%V%m%C%/I,?$@$HA4%W%m%0%i%`$,0lCJ%M%9%H$,?<$/$J$k$N$G(B
$B$&$l$7$/$J$$$J$"(B

$B!!$3$3$O!$C/$+0N$$?M$K%G%6%$%s$rG$$;$?$$$H$3$m$J$s$G$9$,(B…$B!%(B

(5) Thread.mask_interrupt() $B$O%M%9%H$7$?$i@_Dj$r:.$<$F$$$/!$$H$7$?$1$I(B
$BC1$K!$CV$-49$($k!$$H$$$&A*Br;h$b$"$k$N$+!%$3$C$A$N$[$&$,;H$$$d$9$$!)(B

$B:.$<$F$$$/!#$H$$$&$N$,$J$K$r;X$7$F$$$k$N$+<h$l$J$+$C$?$N$GCV$-49$($k%b%G%k$GF0:nNc$r=q$$$F$$$?$@$1$k$H$&$l$7$$$G$9(B

$B!!CV$-49$($kNc$K$D$$$F!$@h$N%3!<%INc$G$9$H!$(B

Thread.interrupt_mask(param1) do
Thread.interrupt_mask(param2) do
# block
end
end

$B$G$O!$:.$<$F$$$/>l9g$O(B block $B$G$O(B param1 & param2
$B$,8z$-$^$9$,!$CV$-49$((B
$B$k>l9g$H$O!$$3$l$r(B param2 $B$7$+(B
$B8z$+$J$/$9$k$N$O$I$&$@$m$&!$$H$$$&$3$H(B
$B$G$9!%30B&$O0l@Z8+$J$$!%(B

$B!!$3$l$@$H!$%O%C%7%e$r;H$$2s$9$H$$$&$+!$$h$/$d$k!V(Bakr
$B$,A&$a$k$@$$$?$$0B(B
$BA4%;%C%H!W!V(Bkosaki
$BG’Dj@dBP0BA4%;%C%H!W$_$?$$$J$N$r:n$C$F$=$l$r;H$&MM$K(B
$B$9$k$H!$Kh2s(B Hash $B$r:n$i$J$/$J$C$F!$$h$/$J$k$+$b!%(B

$B$"$H!$<BAu$O$3$C$A$N$[$&$,3Z$J$s$9$h$M(B…$B!%(B

(2012/06/25 20:32), Tanaka A. wrote:

$B$^$:!"(BSIGINT (^C) $B$G(B ruby $B$r=*N;$G$-$k$3$H$O$H$F$b=EMW$G$9$+$i!"(B
$B$3$l$K$D$$$F$OB(:B$KNc30$K$J$k$Y$-$G$7$g$&!#(B

SIGTERM $B$J$IB>$N%7%0%J%k$bF1MM$@$H;W$$$^$9!#(B

$B$=$l0J30$K$D$$$F$O!"(B100% $B%3%s%Q%A%V%k$H$$$&OC$rB:=E$9$k$J$i!"(B
$B$d$O$j$=$l$b8=>u$I$$jB(:B$KNc30$J$s$8$c$J$$$G$7$g$&$+!#(B
$BB:=E$7$J$$$J$i!"CY1d$5$;$k$H$$$&A
Br;h$b$"$k$+$b$7$l$^$;$s!#(B

$B!!>/$79M$($F8+$^$7$?!%9M$($?2aDx$N%m%0$r=q$$$F$_$k$N$G!$$40U8+D:$1$k$H9,(B
$B$$$G$9!%(B

$B!!>uBV$H$7$F$O!$$d$O$j@h$N%a!<%k$N(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$N#3$D$K$J$k$h$&$J5$$,$7$F$$$^$9$N$G!$$"$kNc30$,$3$l$i(B 3
$B$D$N$I$N>uBV$K(B
$B$9$k$+!$$H$$$&(B API $B$r9M$($F$_$^$7$?!%(B

(a) Thread.interrupt_mask(exception, state) do; end
(b) Thread.interrupt_mask(hash) do; end

state $B$O(B

:immediate_interruptible
:blocking_interruptible
:uninterruptible

$B$N(B 3 $B$D$N%7%s%%k$,;XDj$G$-$k$H$7$^$9!%$=$l$>$l!$%b!<%I(B 0, 1, 2
$B$K$"$?$k(B
$B$H9M$($^$9!%(B

$B!!(B(a) $B$N7A<0$O!$Nc$($P(B

Thread.interrupt_mask(TimeoutError, :immediate_interruptible) do
# block
end

$B$H;XDj$9$k$H!$(Bblcok $B$NCf$G$O!$(BTimeoutError
$B$G3d$j9~$^$l$?$H$-!$B(:B$KNc(B
$B30$rH/@8$9$k!$$H$$$&46$8$G$9!%(B(b) $B$N7A<0$O!$C1$K(B {e1 => state1,
e2 =>
state2, …} $B$N$h$&$K!$J#?t;XDj=PMh$k$H$7$^$9!%(B

Thread.interrupt_mask(param1) do
Thread.interrupt_mask(param2) do
# block (param1 and param2)
end
end

$B!!$3$N$h$&$K!$%M%9%H$7$?>l9g$O!$(Bblock $B$N<B9T$O(B
param1$B!$(Bparam2 $B$NN>J}$N@_(B
$BDj$,8z$/$H$7$^$9!%$?$@$7!$$"$kNc30$K$D$$$F$N;XDj$,>WFM$7$?>l9g$O!$FbB&(B
$B!J$3$N>l9g(B param2$B!K$N@_Dj$,M-8z$@$H$7$^$9!%(B

$B!!$H$j$"$($:!$(Bprimitive $B$J(B
API$B!J$r9M$($k%M%?!K$H$7$F!$LVMe$7$F$$$k$H;W$&(B
$B$N$G$9$,!$$b$79M$(Mn$H$7$F$$j$^$7$?$i$4;XE&2<$5$$!J$3$3$,40c$$$7$F$$$?(B
$B$i9s$$!K!%<B:]$K;H$o$;$k$?$a$N(B API
$B$K$D$$$F$O!$L>A0$J$I!$$h$j$h$$$b$N$,(B
$B$"$k$+$H;W$$$^$9$,!$$^$:$O(B primitive $B$r!%(B

$B!!$3$N$H$-!$%G%U%)%k%H$O8_49@-(B 100%
$B$NJ}?K$H$$$&$3$H$G!$A4$F$NNc30$,(B
immediate_interruptible $B$@$H$7$^$9!%(B

begin
# $B2?$+=hM}(B
ensure
# $B%j%=!<%92rJ|=hM}(B
end

$B$H$$$&!$$h$/$"$j$=$&$J=hM}$,$"$C$?$H$-!$%j%=!<%92rJ|=hM}$O$J$k$Y$/$J$i2r(B
$BJ|$5$l$?$/$J$$!$$?$@$7!$(B^C$B!$$b$7$/$O(B SIGTERM
$B$J$I$N%7%0%J%k$O(B blocking
$B=hM}$7$=$&$K$J$C$?!$$b$7$/$O$7$F$$$k;~$O3d$j9~$^$l$k$N$r5v$9!$$H$$$&=hM}(B
$B$O<!$NMM$K$J$k$G$7$g$&$+!%(B

begin
# $B2?$+=hM}(B
ensure
Thread.mask_interrupt(Exception, :uninterruptible) do
# $B0lEYA4It3d$j9~$6X;$K$7$F(B
Thread.mask_interrupt(SignalException, :blocking_interruptible) do
# $B%7%0%J%k$@$13d$j9~$_$r5v$7$F(B
# $B%j%=!<%92rJ|=hM}(B
end
end
end

$B!!#2$D=q$+$J$$$H$$$1$J$$$N$O!$$A$g$C$H>iD9$+$b$7$l$^$;$s$M!%(BHash
$B$GEO$9(B
$BJ}<0$G$O!$(B

begin
# $B2?$+=hM}(B
ensure
Thread.mask_interrupt(Exception => uninterruptible,
SignalException, :blocking_interruptible) do
# $B%7%0%J%k$@$13d$j9~$_$r5v$7$F(B
# $B%j%=!<%92rJ|=hM}(B
end
end

$B$H$J$C$F!$$A$g$C$H%^%7$+$J!)(B

$B!!=q$$$F$$$F!$=P$F$-$?5?LdE@$G$9!%(B

(1) $B%7%0%J%k$r5v$9$H8@$C$F$b!$(BSIGUSR1 $B$H$+$b5v$7$F$$$$$N$+$J!%(B
(2) POSIX $B$$?$$$K!$$3$N%a%=%C%I$O(B blocking $B$H$+!$$9$Y$F$-$A$s$H(B
$B=q$-O"$M$kI,MW$,$"$k$N$+$J!%$+$J$j!$L5M}$J5$$,$9$k(B
$B!!!J$=$b$=$b!$2?$,$I$N%a%=%C%I$r8F$S=P$9$+$o$+$i$J$$5$$,!K!%(B
(3) $B%i%$%V%i%j$N;j$k=j$G$3$s$J$N=q$+$l$?$i%O%C%7%e$,BgNLH/@8$7$F!$(B
$B%*!<%P%X%C%I$GBgJQ$K$J$C$?$j$7$J$$$@$m$&$+(B…$B!%(B
$B$=$b$=$b!$$3$l$C$FB?MQ$9$k$s$@$m$&$+!%(B
(4) $B%V%m%C%/$r;}$?$J$$(B Thread.mask_interrupt()
$B$O5v$9$Y$-$@$m$&$+!%(B
$B!!!J0UL#$H$7$F$O!$!V$3$N8F$S=P$70J9
$O$3$N@_Dj$G!W!$$H$$$&46$8!K(B
$B$J$s$H$J$/!$5v$5$J$$J}$,$$$$$h$&$J5$$,$9$k$s$@$1$I(B
(5) Thread.mask_interrupt()
$B$O%M%9%H$7$?$i@_Dj$r:.$<$F$$$/!$$H$7$?$1$I(B
$BC1$K!$CV$-49$($k!$$H$$$&A*Br;h$b$"$k$N$+!%$3$C$A$N$[$&$,;H$$$d$9$$!)(B

(2012/06/26 5:07), Tanaka A. wrote:

$BL>A0$G$9$,!"(BThread.interruptable_at(:blocking) $B$H$+$O$I$&$+$J$!!#(B

$B!!$3$l$@$H!$Nc30%/%i%9$r;XDj$9$k>l9g!$(B

Thread.interruptable_at(:blocking, TimeoutError)

$B$_$?$$$K=q$/$N!)(B

end
$B30B&$,(B :immediate_interruptible $B$G$"$k$H$9$k$H!"$3$l$O(B race
$B$,$"$j$^$9$h$M!#(B

$B!V2?$+=hM}!W$GNc30$,5/$-$F!"(Bensure $B@a$KF~$C$?8e!"(B
Thread.mask_interrupt(Exception, :uninterruptible) $B$r8F$S=P$9A0$K(B
$BHsF14|%$%Y%s%H$K$h$kNc30$,5/$-$k$H!"%j%=!<%93+J|=hM}$,%9%-%C%W$5$l$^$9!#(B

$Be$O$=$3$G$ONc30$O5/$-$J$$$N$+$b$7$l$^$;$s$,(B…

$B!!3N$+$K!$6D$k$H$*$j$G$9!%?2$$1$?F,$G$O!$$H$j$"$($:(B

(1) $B!Ve$O$=$3$G$ONc30$O5/$-$J$$!W$3$H$r;EMM$K$9$k(B
(2) ensure $B$K:Y9)$9$k!J$"$^$j$d$j$?$/$J$$!K(B
(3) $BMxMQ<T$,(B immediate $B$K$7$J$$(B

$B$,9M$($i$l$k$H;W$$$^$9!%$I$l$,$$$$$G$7$g$&!%$^$?$O!$B>$NA*Br;h$O$"$k$G(B
$B$7$g$&$+!%(B

2012$BG/(B6$B7n(B26$BF|(B 5:15 SASADA Koichi [email protected]:

(2012/06/26 5:07), Tanaka A. wrote:

$BL>A0$G$9$,!"(BThread.interruptable_at(:blocking) $B$H$+$O$I$&$+$J$!!#(B

$B!!$3$l$@$H!$Nc30%/%i%9$r;XDj$9$k>l9g!$(B

Thread.interruptable_at(:blocking, TimeoutError)

$B$_$?$$$K=q$/$N!)(B

$B$=$&$J$j$^$9$M!#(B

$B!!3N$+$K!$6D$k$H$*$j$G$9!%?2$$1$?F,$G$O!$$H$j$"$($:(B

(1) $B!Ve$O$=$3$G$ONc30$O5/$-$J$$!W$3$H$r;EMM$K$9$k(B
(2) ensure $B$K:Y9)$9$k!J$"$^$j$d$j$?$/$J$$!K(B
(3) $BMxMQ<T$,(B immediate $B$K$7$J$$(B

$B$,9M$($i$l$k$H;W$$$^$9!%$I$l$,$$$$$G$7$g$&!%$^$?$O!$B>$NA*Br;h$O$"$k$G(B
$B$7$g$&$+!%(B

kosaki $B$5$s$N!V#19TL$G(B blocking_interruptible
$B$K$7$FFsEY$HJQ$($J$$!#!W$H$+!“(B
$B;d$N!V(B(100% $B%3%s%Q%A%V%k$H$$$&OC$r(B) $BB:=E$7$J$$$J$i!”(B
$BCY1d$5$;$k$H$$$&A*Br;h$b$“$k$+$b$7$l$^$;$s!#!W(B
$B$H$+$,!”$=$N$X$s$KBP$9$kI=L@$J$s$8$c$J$$$G$9$+$M$'!#(B

$B$^$?!“@N$N$G(B Thread.delay_interrupt $B$N5U$,$J$$$H$$$&$N$b!”(B
$B$=$&$@$C$?$N$+$b$7$l$^$;$s!#(B

kosaki $B$5$s$O(B (3) $B$G!"(B
$B;d$O$I$A$i$+$H$$$&$H%G%U%)%k%H$rJQ$($F$7$^$&$[$&$K8~$$$F$$$k$+$J!#(B

2012$BG/(B6$B7n(B26$BF|(B 3:40 SASADA Koichi [email protected]:

$B$H9M$($^$9!%(B
$BL>A0$G$9$,!"(BThread.interruptable_at(:blocking)
$B$H$+$O$I$&$+$J$!!#(B

$BJ|$5$l$?$/$J$$!$$?$@$7!$(B^C$B!$$b$7$/$O(B SIGTERM $B$J$I$N%7%0%J%k$O(B
blocking
# $B%j%=!<%92rJ|=hM}(B
end
end
end

$B30B&$,(B :immediate_interruptible $B$G$“$k$H$9$k$H!”$3$l$O(B race
$B$,$"$j$^$9$h$M!#(B

$B!V2?$+=hM}!W$GNc30$,5/$-$F!“(Bensure $B@a$KF~$C$?8e!”(B
Thread.mask_interrupt(Exception, :uninterruptible) $B$r8F$S=P$9A0$K(B
$BHsF14|%$%Y%s%H$K$h$kNc30$,5/$-$k$H!"%j%=!<%93+J|=hM}$,%9%-%C%W$5$l$^$9!#(B

$Be$O$=$3$G$ONc30$O5/$-$J$$$N$+$b$7$l$^$;$s$,(B…

kosaki $B$5$s$N!V#19TL$G(B blocking_interruptible
$B$K$7$FFsEY$HJQ$($J$$!#!W$H$+!"(B
$B;d$N!V(B(100% $B%3%s%Q%A%V%k$H$$$&OC$r(B) $BB:=E$7$J$$$J$i!"(B
$BCY1d$5$;$k$H$$$&A*Br;h$b$"$k$+$b$7$l$^$;$s!#!W(B
$B$H$+$,!"$=$N$X$s$KBP$9$kI=L@$J$s$8$c$J$$$G$9$+$M$’!#(B

$B$^$?!"@N$N$G(B Thread.delay_interrupt $B$N5U$,$J$$$H$$$&$N$b!"(B
$B$=$&$@$C$?$N$+$b$7$l$^$;$s!#(B

kosaki $B$5$s$O(B (3) $B$G!"(B
$B;d$O$I$A$i$+$H$$$&$H%G%U%)%k%H$rJQ$($F$7$^$&$[$&$K8~$$$F$$$k$+$J!#(B

$B;d<+?H$O8=:_$N;EMM$O2u$l$F$$$k$H;W$C$F$*$j!"%G%U%)%k%H$rJQ$($k$N$K$O(B
$BH?BP$8$c$J$$$s$G$9$,$I$&JQ$($k$H$$$&0U?^$G$7$g$&$+!#(B
$B%G%U%)%k%H$,(B :blocking $B$H$$$&0UL#$G$7$g$&$+!)(B

$BJL7o$G$9$,!"(Bsigprocmask(2)$B$H$+$H0c$C$F(B
:blocking$BCf$G$bG[Aw$5$l$F$/$k$3$H$,$"$k(B
$B%;%^%s%F%#%/%9$J$N$G(B :blocking $B$H$$$&L>A0$K$OH?BP$G$9!#(B