toRuby & guRuby åºå¼µç ã§ã·ã°ãã«ã«ã¤ãã¦ãã£ã¦ãã®ã§ãé¢é£ãã¦æ¸ãã¦ã¿ã¾ãã
ã©ã®ãããªæã«ã·ã°ãã«ãã³ãã©ãå®ç¾©ããã®ã
ã©ã®ãããªæã«ã·ã°ãã«ãã³ãã©ãå®ç¾©ããã®ãã¨ãã話ãããã¾ããã
UNIXã®ãã¼ã¢ã³ããã°ã©ã ã¯ãä½ãç±æ¥ãªã®ããããã¾ããããSIGHUP ã§è¨å®ãã¡ã¤ã«ã®åèªã¿è¾¼ã¿ãè¡ãã®ãæ £ç¿ã«ãªã£ã¦ãã¾ãã SIGHUP ã¯ããã©ã«ãåä½ã§ã¯ããã°ã©ã ãçµäºããã¦ãã¾ãã ããªã®ã§ãSIGHUP ã§ç¹å¥ãªå¦çãè¡ãããããã°ã©ã ã¯ã·ã°ãã«ãã³ãã©ãå®ç¾©ãã¦ãã¾ãã
æ¬æ¥ SIGHUP ã¯ç«¯æ«ãçµäºããæã«ç«¯æ«ä¸ã§åãã¦ããããã°ã©ã ã«å¯¾ãã¦OSãçºè¡ããããã®ãã®ã§ãã
ãã¨ãã°ã端æ«ã¨ãã¥ã¬ã¼ã¿ãéãã¦ã
% sleep 9999
ã¨å®è¡ãã¦ãç¶æ ã§ç«¯æ«ã¨ãã¥ã¬ã¼ã¿ãéãã㨠sleep ããã»ã¹ã« SIGHUP ãéããã¾ããå¥ã®ç«¯æ«ãã strace ã³ãã³ãã§ãã®ããã»ã¹ãè¦ã¦ã㨠SIGHUP ã§çµäºãã¦ãããã¨ããããã¾ãã
% sudo strace -p 26416
Process 26416 attached
restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=26390, si_uid=1000} ---
+++ killed by SIGHUP +++
ã³ãã³ããã&ãã¤ãã§ããã¯ã°ã©ã³ãã§èµ·åãã¦ãã¦ãåãã§ãã端æ«ãçµäºãã¦ãããã°ã©ã ãçµäºãããªãããã«ããã«ã¯ãSIGHUP ãç¡è¦ãããã端æ«ããããã»ã¹ãåãé¢ãå¿ è¦ãããã¾ããã¡ããã¨ä½ããã¦ãããã¼ã¢ã³ããã°ã©ã ã¯ç«¯æ«ããåãé¢ãããã«ä½ã£ã¦ããã¯ãã§ããRuby ã ã¨ããã°ã©ã ä¸ã§
Process.daemon
ã¨ããã°ããã以éã¯ç«¯æ«ããåãé¢ããã¦åä½ããããã«ãªãã¾ãã
SIGTERM 㯠kill ã³ãã³ãã®ããã©ã«ãã·ã°ãã«ãªã®ã§ãããã»ã¹ã殺ãæã«ä¸çªè¯ã使ããã¾ããããã°ã©ã ã«ãã£ã¦ã¯çµäºæã«ç¹å¥ãªå¦çãè¡ããªãã¨æ´åæ§ãå£ãã¦ãã¾ããã®ãããã¾ãããã®å ´å㯠SIGTERM ã®ã·ã°ãã«ãã³ãã©ãå®ç¾©ãã¦ãå¦çãè¡ã£ã¦ããçµäºããããã«ãã¦ããå¿ è¦ãããã¾ãã
SIGWINCH ã¯ã端æ«ã®å¤§ããã夿´ãããæã«ããã»ã¹ã«ãããç¥ãããããã®ã·ã°ãã«ã§ãã端æ«ä¸ã§æ¬¡ã®ã³ãã³ããå®è¡ãã¦ããã端æ«ã®ãµã¤ãºã夿´ããã¨ãWINCHãã¨è¡¨ç¤ºããã¾ãã
% ruby -e 'trap(:WINCH){puts "WINCH"}; sleep'
Vim ã less çã®ç«¯æ«å ¨ä½ã使ç¨ããã¢ããªã¯ SIGWINCH ãéç¥ãããæã«ç»é¢ã®åæç»ãè¡ãããã«ãªã£ã¦ãã¾ãã
ã·ã°ãã«ãã³ãã©å ã§ã®å¦ç
toRuby & guRuby ã®å ´ã§ãè¨ãã¾ããããã·ã°ãã«ãã³ãã©ä¸ã§ã¯ãã¾ãè¤éãªãã¨ã¯ãã£ã¦ã¯ãããªãã§ããã¨ãããããã§ãããã¨ã¯ããªãéããã¦ãã¨æãã¾ãã
Ruby ã®å ´åãã·ã°ãã«ãã³ãã©ä¸ã§ã©ã®ãããªæä½ãã§ããã®ãã«ã¤ãã¦ã¯ããã¶ãããã¥ã¡ã³ãã¯ãªãããããªããã¨æãã®ã§ãããå°ãªãã¨ã Ruby 1.9.3 ã§ã¯ IO å¦çããã¨ãã°ä¸ã®ä¾ã§ä½¿ã£ã puts ãå®å ¨ã§ã¯ããã¾ãããã·ã°ãã«ã®ä¾ã示ãã®ã«ç°¡åãªã®ã§ãã使ãããã¡ãªã®ã§ããâ¦ã
ãã¨ãã° Ruby 1.9.3 ã§æ¬¡ã®ã³ãã³ããå®è¡ãã¦ç«¯æ«ãµã¤ãºã夿´ããã¨ããã°ã©ã ãçµäºãã¾ãã
% ruby -e 'trap(:WINCH){puts "WINCH"}; loop{puts "main"}'
...
main
main
main
main
-e:1:in `write': deadlock; recursive locking (ThreadError)
from -e:1:in `puts'
from -e:1:in `puts'
from -e:1:in `block in <main>'
from -e:1:in `call'
...
Ruby 2.0.0 以éã§ã¯çºçããªãã®ã§ãIO ã¯ã·ã°ãã«ã«å¯¾ãã¦å®å ¨ã«ãªã£ãã®ããããã¾ããã
ä¸ã®ä¾ã§ã¯ Ruby ããããããã¯ãæ¤åºãã¦è½ã¡ã¦ãããã®ã§ããã®ã§ãããèªåã§ä½ã£ãã©ã¤ãã©ãªã使ç¨ããå ´åã¯ãã¼ã¿ãå£ããªãããã«å¯¾å¿ããå¿ è¦ãããã¾ãã
Mutex ã使ã£ã¦æä»å¶å¾¡ããæ¹æ³ã¯ãã¾ãåãã¾ããã
次ã®ã¹ã¯ãªãã㯠SIGINT ãåããã¨ãæä»é åã§ãInterrupt!ãã¨è¡¨ç¤ºãã¾ãã
mutex = Mutex.new trap :INT do mutex.synchronize do puts 'Interrupt!' sleep 1 end end sleep
SIGINT ã¯ç«¯æ«ä¸ã§ Ctrl-C ãå ¥åããã¨ãã©ã¢ã°ã©ã³ãããã»ã¹ã«å¯¾ãã¦éç¥ãããã·ã°ãã«ã§ãã
ãã®ã¹ã¯ãªãããåãã㦠Ctrl-C ãæ¼ãã¨ã¨ã©ã¼ã«ãªãã¾ãã
% ruby test.rb
^Ctest.rb:4:in `synchronize': can't be called from trap context (ThreadError)
from test.rb:4:in `block in <main>'
from test.rb:10:in `call'
from test.rb:10:in `sleep'
from test.rb:10:in `<main>'
Mutex#synchronize ã¯ã·ã°ãã«ãã³ãã©ä¸ã§ã¯è¨±ãããªãå¦çã®ããã§ãã
ãªããRuby 1.9.3 ã§ã¯ Ctrl-C ã2åæ¼ãã¨å¥ã®ã¨ã©ã¼ã«ãªãã¾ãã
% ruby test.rb
^CInterrupt!
^C<internal:prelude>:8:in `lock': deadlock; recursive locking (ThreadError)
from <internal:prelude>:8:in `synchronize'
from test.rb:4:in `block in <main>'
from test.rb:6:in `call'
from test.rb:6:in `sleep'
from test.rb:6:in `block (2 levels) in <main>'
from <internal:prelude>:10:in `synchronize'
from test.rb:4:in `block in <main>'
from test.rb:10:in `call'
from test.rb:10:in `sleep'
from test.rb:10:in `<main>'
1.9.3 ã§ã¯ Mutex#synchronize ã¯ç¦æ¢ããã¦ããªãããã§ãããMutex#synchronize ãããã¯å®è¡ä¸ã«ã¾ãã·ã°ãã«ãçºçãã¦ãåã Mutex ã§æä»å¶å¾¡ãããã¨ãã¦ãããããã¯ã«ãªãã¾ãã
次ã®ããã« Mutex#synchronize ã§ã¯ãªããMutex#try_lock ã使ç¨ããã¨åãããã§ãã(Ctrl-C ã¯å¹ããªãã®ã§ãããã°ã©ã ã忢ããã«ã¯ Ctrl-Z ã㦠kill %1 ããããä»ã®ç«¯æ«ãã kill ãã¦ãã ãã)
mutex = Mutex.new trap :INT do if mutex.try_lock puts 'Interrupt!' sleep 1 mutex.unlock end end sleep
ããã試ãã¦ã¦æ°ãã¤ããã®ã§ãããRuby 1.9.3 㨠2.x ã§ã¯ã·ã°ãã«ãã³ãã©ã®å®è¡ã®ãããããå°ãç°ãªãããã§ãã
1.9.3 ã§ã¯ã·ã°ãã«çºçã®åº¦ã«ãã³ãã©ãå®è¡ããã¾ãã(ä¸ã®ã¹ã¯ãªããã 㨠if ã®æ¡ä»¶ãæºãããªãã®ã§ç¡è¦ããã)ã2.x ã§ã¯ãã³ãã©å®è¡ä¸ã«çºçããã·ã°ãã«ã¯æºãããã¦ãã¦ããã³ãã©ãããã¯ãæããã¨éç¥ãããããã§ãã
ä¸ã®ããã«ãã³ãã©å
ã§ã Mutex#try_lock ã¯ä½¿ããããã§ãããããã¯æä»ãç²å¾ã§ããªããã°ã·ã°ãã«ãç¡è¦ãã¦ãã¾ããã¨ã«ãªãã®ã§ããã¾ãããããã¾ããã
çµå±ã·ã°ãã«ãã³ãã©å ã§ä½ãè¤éãªå¦çãè¡ããã¨ãããã¨ãééããªã®ã ã¨æãã¾ãã
ã·ã°ãã«ãã³ãã©å ã§ã¯ã·ã°ãã«ãçºçãããã¨ã表ããã©ã°ãç«ã¦ããããã«ãã¦ãããããã°ã©ã ã®é½åã®ããã¿ã¤ãã³ã°ã§ãã®ãã©ã°ãè¦ã¦ã·ã°ãã«ã«å¿ããå¦çãè¡ãã®ãããã¨æãã¾ãã
mutex = Mutex.new sigint = false Thread.new do loop do if sigint sigint = false mutex.synchronize do puts 'Interrupt!' sleep 1 end end sleep 0.1 end end trap :INT do sigint = true end sleep
ä¸ã®ããã°ã©ã ã¯ãã·ã°ãã«ãã³ãã©å ã§ã¯ sigint 夿°ã®å¤ãè¨å®ãã¦ããã ãã§ãå®éã®å¦çã¯ã¹ã¬ããã®ä¸ã§è¡ã£ã¦ãã¾ãã
ãã®ä¾ã®ã¾ã¾ã ã¨ã·ã°ãã«å¦çä¸ã«ã·ã°ãã«ãé£ç¶çºçãã¦ã1ååããå¦çãããªãã¨ããsleep 0.1 ãã¦ããã®ã®ããã©ã°ãã§ãã¯ããã¸ã¼ã«ã¼ãã£ã½ãã¨ããããã¾ãã¡ããããã¾ããã
ã·ã°ãã«ãã³ãã©ä¸ã§ Array#push ãã¦ãã·ã°ãã«å¦çæã« Array#pop ããã°åæ°ã®åé¡ã¯ã¯ãªã¢ã§ãããããªæ°ããã¾ããArray 㯠Ruby æ¨æºã§ C ã§æ¸ãããã¯ã©ã¹ãªã®ã§ã·ã°ãã«ãã³ãã©ä¸ã§ä½¿ã£ã¦ãã¢ãããã¯ã«å¦çã§ããããããªããã¨æãã¾ãã
ãã¸ã¼ã«ã¼ãã®æ¹ã¯ Thread.stop 㨠Thread#run ã使ãã®ãããããããã¾ããããããã·ã°ãã«ãã³ãã©ä¸ã§ä½¿ã£ã¦ãããããªæ°ããã¾ãããªãã¨ãªãã
ä½ããã£ã¨ãã¾ãæ¹æ³ãããã°æãã¦ãã ããã