From: nobu.nakada@... Date: 2003-08-19T14:13:30+09:00 Subject: [ruby-list:38152] Re: ポートが閉じているときの例外など なかだです。 At Tue, 19 Aug 2003 01:44:54 +0900, Takahiro Kambe wrote: > LAN上のホストを相手にすると、EINPROGRESSの場合にgetsockopt(2)でチェッ > クしない場合は、 > > 1. connect()失敗 (EINPROGRESS) > 2. connect()失敗 (EINVAL) > 3. getsockopt()で ECONNREFUSED を検知 > > となります。 > > CPUが高速、メモリやハードディスクがいっぱいになっても、システムコール > にかかるオーバーヘッドは、(システムコールの呼び出しを伴わない)ライブラ > リに比べるとはるかに大きいものです。必要のないシステムコールの呼び出し > をやめることができることができれば、それに越したことはありません。 1の時点でECONNREFUSEDが分かっていない場合には、いわおかさんの例 ([ruby-list:38142])のように、逆にgetsockopt()が無駄になるように 思えますが。 EALREADYを別にすればいい? > > 対応としては、FreeBSD(*BSD全部?)でもWAIT_IN_PROGRESSを有効にす > > るということでいいんでしょうか。全システムで有効にしたほうがい > > いのかな? > 以下の環境の確認はできました。 > > NetBSD 1.6 and current > FreeBSD 2.2.8 > OpenBSD 3.3 それぞれ、__NetBSD__, __FreeBSD__, __OpenBSD__でいいでしょうか。 Index: ext/socket/socket.c =================================================================== RCS file: /cvs/ruby/src/ruby/ext/socket/socket.c,v retrieving revision 1.99 diff -u -2 -p -r1.99 socket.c --- ext/socket/socket.c 1 Aug 2003 07:02:54 -0000 1.99 +++ ext/socket/socket.c 19 Aug 2003 05:10:21 -0000 @@ -732,4 +732,7 @@ thread_write_select(fd) #define WAIT_IN_PROGRESS 10 #endif +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#define WAIT_IN_PROGRESS 1 +#endif static int @@ -744,4 +747,5 @@ ruby_connect(fd, sockaddr, len, socks) #ifdef WAIT_IN_PROGRESS int wait_in_progress = -1; + int sockerr, sockerrlen = sizeof(sockerr); #endif @@ -780,4 +784,13 @@ ruby_connect(fd, sockaddr, len, socks) case EINPROGRESS: #endif +#ifdef WAIT_IN_PROGRESS + status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen); + if (status) break; + if (sockerr) { + status = -1; + errno = sockerr; + break; + } +#endif #ifdef EALREADY case EALREADY: @@ -792,6 +805,4 @@ ruby_connect(fd, sockaddr, len, socks) case EINVAL: if (wait_in_progress-- > 0) { - int sockerr, sockerrlen = sizeof(sockerr); - /* * connect() after EINPROGRESS returns EINVAL on -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦