読者です 読者をやめる 読者になる 読者になる

中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

Rubyコンテキストスイッチの不思議・その2

Rubyコンテキストスイッチの不思議 - LinuxとApacheの憂鬱の続き

Ruby extension内ではコンテキストスイッチは起きないハズなのに
EventMachine内では確かに起きてる!の謎

EventMachineのソースを読む

詳しい事は省略するが

  • pure_ruby.rb => run_machine

ココでextensionの世界に入って来る。
んで、地続きで進み・・・

  • cmain.cpp => EventMachine->Run()

で、EventMachineに入る

  • em.cpp => EventMachine->Run() => _RunEpollOnce() => epoll_wait

ココが問題の個所。

でもあからさまに変な奴がいるぜ!

#ifdef BUILD_FOR_RUBY
  :
TRAP_BEG;
s = epoll_wait (epfd, epoll_events, MaxEvents, 0);
TRAP_END;

100% 間違いない!!w

で、em.h に居ました。

#define TRAP_BEG rb_enable_interrupt()
#define TRAP_END do { rb_disable_interrupt(); rb_thread_check_ints(); } while(0)

へー
rb_enable_interrupt();
なんてモノがあるんだね〜

早速使ってみる。

#include "rubysig.h"
  :
  :
VALUE method_myext3(VALUE self) {
  printf("TEST2 START\n");
  fflush(stdout);
  TRAP_BEG;  // ### Allow to interrupt
  sleep(3);
  TRAP_END;  // ### Deny to interrupt
  printf("TEST2 END       **** HERE ****\n");
  fflush(stdout);
  return Qnil;
}

しかし、コンパイル時に警告!
動くんだけどさ・・・

#warning rubysig.h is obsolete

Obsoluteじゃ仕方ない。。。

最新のやり方はどうすんのさ?
ヘッダを攫うと"intern.h"ってのが有るけど・・・情報が少ないなぁ。。

http://www.ruby-forum.com/topic/2914075#1029667

BLOCKING_REGION ってマクロ使うと簡単だぜ!

エライ!
って・・・
どこにも定義されてねーじゃんかYO!!1.9.2の話かっ!!
もういいや、このままコピってこよ

#!/usr/bin/env ruby
puts '=== Interruptable mode ==='
require 'myext'
include MyExt
def test1(i)
  myext1 i
end

def test2
  myext3
end
#define BLOCKING_REGION(func, arg) (long)rb_thread_blocking_region((func), (arg), RUBY_UBF_IO, 0)
VALUE mysleep(void *a){
  sleep(3);
  return 0;
}
VALUE method_myext3(VALUE self) {
  printf("TEST3 START\n");
  fflush(stdout);
  (void)BLOCKING_REGION(mysleep, 0);
  printf("TEST3 END       **** HERE ****\n");
  fflush(stdout);
  return Qnil;
}

結果

=== Interruptable mode ===
test1 (0) start
test1 end
test1 (1) start
test1 end
TEST3 START
test1 (2) start
test1 end
test1 (3) start
test1 end
test1 (4) start
test1 end
TEST3 END       **** HERE ****

ちゃんとコンテキストスイッチが動いたー!

なるほどね!良く考えられてるな〜
でもこれは結構恐ろしい機構なので、不用意には使えない。

自分の使ってるExtensionも念の為にgrepしとこ・・・