From: SATOH Fumiyasu Date: 2007-10-23T14:20:51+09:00 Subject: [ruby-dev:32131] Re: 拡張ライブラリ内での SIGVTALRM さとうふみやす @ OSS テクノロジです。 At Mon, 24 Sep 2007 23:03:27 +0900, とみたまさひろ wrote: > 今までそのような認識は無かったのですが、 Solaris10 上の MySQL/Ruby 実行 > 中に poll() が SIGVTALRM で EINTR になって失敗するという事象があったと > いう連絡を受けたので、どうしたものかと…。 今度 Solaris 10 で Ruby を試そうと思っていたので 気になったので試してみました。C のソースは以下: #include #include #include #include #include #include int sig_vtalrm_count = 0; void sig_vtalrm(int sig) { printf("******** SIGVTALRM (%d) ********\n", sig); sig_vtalrm_count++; } int main(void) { struct sigaction sigact; int i, j; struct itimerval itime, itime2; struct pollfd fds[1]; int fd_ready; int poll_count = 0; int itime_timeout = 100; /* 100 msec */ int poll_timeout = 1000; /* 1000 msec */ sigact.sa_handler = sig_vtalrm; sigact.sa_flags = 0; sigaction(SIGVTALRM, &sigact, NULL); itime.it_interval.tv_sec = itime.it_value.tv_sec = 0L; itime.it_interval.tv_usec = itime.it_value.tv_usec = itime_timeout * 1000L; errno = 0; setitimer(ITIMER_VIRTUAL, &itime, NULL); printf("setitimer errno %d (%s)\n", errno, strerror(errno)); fds[0].fd = 0; fds[0].events = POLLIN; for (i = 0; i < 10; i++) { getitimer(ITIMER_VIRTUAL, &itime2); printf("pre poll : gettimer %ld sec, %ld usec\n", itime2.it_value.tv_sec, itime2.it_value.tv_usec); errno = 0; fd_ready = poll(fds, 1L, poll_timeout); poll_count++; printf("poll fd ready %d\n", fd_ready); printf("poll fd events %x\n", fds[0].revents); printf("poll errno %d (%s)\n", errno, strerror(errno)); getitimer(ITIMER_VIRTUAL, &itime2); printf("post poll: gettimer %ld sec, %ld usec\n", itime2.it_value.tv_sec, itime2.it_value.tv_usec); for (j = 0; j < 0xFFFFFF; j++) {} } puts(""); printf("poll count: %d (%d msec)\n", poll_count, poll_count * poll_timeout); printf("sigvtalrm count: %d (%d sec)\n", sig_vtalrm_count, sig_vtalrm_count * itime_timeout); return 0; } poll(2) も set/getitimer(2) も初めて使うので自信がない ですが、あってますかね? コンパイル方法と実行手順は: $ /usr/sfw/bin/gcc -Wall a.c && time ./a.out $ /usr/sfw/bin/gcc -D_REENTRANT -lthread -Wall a.c && time ./a.out $ /opt/SUNWspro/bin/cc a.c && time ./a.out $ /opt/SUNWspro/bin/cc -D_REENTRANT -lthread a.c && time ./a.out $ /opt/SUNWspro/bin/cc -mt a.c && time ./a.out いずれも結果は以下のようになり、poll() で EINTR は発生しませんでした (SPARC, Intel とも): $ /usr/sfw/bin/gcc -Wall a.c && time ./a.out setitimer errno 0 (Error 0) pre poll : gettimer 0 sec, 100000 usec poll fd ready 0 poll fd events 0 poll errno 0 (Error 0) post poll: gettimer 0 sec, 100000 usec pre poll : gettimer 0 sec, 40000 usec poll fd ready 0 poll fd events 0 poll errno 0 (Error 0) post poll: gettimer 0 sec, 40000 usec ******** SIGVTALRM (28) ******** pre poll : gettimer 0 sec, 100000 usec poll fd ready 0 poll fd events 0 poll errno 0 (Error 0) post poll: gettimer 0 sec, 100000 usec pre poll : gettimer 0 sec, 30000 usec poll fd ready 0 poll fd events 0 poll errno 0 (Error 0) post poll: gettimer 0 sec, 30000 usec ******** SIGVTALRM (28) ******** pre poll : gettimer 0 sec, 60000 usec poll fd ready 0 poll fd events 0 poll errno 0 (Error 0) post poll: gettimer 0 sec, 60000 usec *** 省略 *** poll count: 10 (10000 msec) sigvtalrm count: 6 (600 sec) real 0m10.735s user 0m0.650s sys 0m0.013s > この辺について対処しているライブラリを見たこと無いのですが、どうするの > が正しいのでしょうか。 SIGVTALRM で poll(2) が EINTR になるかどうかはともかく、 poll(2) で EINTR が発生する可能性はあるので、 EINTR を補足していないライブラリが悪いんじゃないでしょうか? -- -- Name: SATOH Fumiyasu / fumiyas @ osstech.co.jp -- Business Home: http://www.OSSTech.co.jp -- Personal Home: http://www.SFO.jp/blog/