Project

General

Profile

Bug #10915

Error in FTPTest#test_abort and test_status on Solaris

Added by ngoto (Naohisa Goto) over 5 years ago. Updated over 5 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.3.0dev (2015-02-26) [sparc64-solaris2.10]
[ruby-dev:48885]

Description

Solaris 10 にて、make test-all で以下のエラーが出ます。
(r49732にて確認)

  1) Error:
FTPTest#test_abort:
Net::ReadTimeout: Net::ReadTimeout
    /XXXXXXXXXX/lib/net/protocol.rb:158:in `rescue in rbuf_fill'
    /XXXXXXXXXX/lib/net/protocol.rb:152:in `rbuf_fill'
    /XXXXXXXXXX/lib/net/protocol.rb:134:in `readuntil'
    /XXXXXXXXXX/lib/net/ftp.rb:1108:in `gets'
    /XXXXXXXXXX/lib/net/ftp.rb:1113:in `readline'
    /XXXXXXXXXX/lib/net/ftp.rb:290:in `getline'
    /XXXXXXXXXX/lib/net/ftp.rb:301:in `getmultiline'
    /XXXXXXXXXX/lib/net/ftp.rb:886:in `abort'
    /XXXXXXXXXX/test/net/ftp/test_ftp.rb:726:in `test_abort'

  2) Error:
FTPTest#test_status:
Net::ReadTimeout: Net::ReadTimeout
    /XXXXXXXXXX/lib/net/protocol.rb:158:in `rescue in rbuf_fill'
    /XXXXXXXXXX/lib/net/protocol.rb:152:in `rbuf_fill'
    /XXXXXXXXXX/lib/net/protocol.rb:134:in `readuntil'
    /XXXXXXXXXX/lib/net/ftp.rb:1108:in `gets'
    /XXXXXXXXXX/lib/net/ftp.rb:1113:in `readline'
    /XXXXXXXXXX/lib/net/ftp.rb:290:in `getline'
    /XXXXXXXXXX/lib/net/ftp.rb:301:in `getmultiline'
    /XXXXXXXXXX/lib/net/ftp.rb:319:in `getresp'
    /XXXXXXXXXX/lib/net/ftp.rb:900:in `status'
    /XXXXXXXXXX/test/net/ftp/test_ftp.rb:759:in `test_status'

net/ftp の abort と status は、以下のように MSG_OOB オプションを付けて、
帯域外データとして送信しています。

 @sock.send(line, Socket::MSG_OOB)

これを test_ftp.rb 内の sock.recv(1024) にて受けています。
Linux などでは、これで受信できているようですが、
Solaris では、ioctl() SIOCATMARK 要求をする必要があるような感じです。
しかし、この ioctl は Rubyレベルでは、少なくともポータブルには、出す方法がありません。

かわりに、OOBデータも通常データとみなして受信するソケット・オプション
SO_OOBINLINE を受信側のソケット・オプションに指定すると、
タイムアウトすることはなくなりましたが、以下のFailureが出ました。

  2) Failure:
FTPTest#test_abort [/user3/gen-info/ngoto/testruby/daily/src/sparc64-cc12-trunk-49756/test/net/ftp/test_ftp.rb:727]:
<"ABOR\r"> expected but was
<"ABOR\r\n">.

  3) Failure:
FTPTest#test_status [/user3/gen-info/ngoto/testruby/daily/src/sparc64-cc12-trunk-49756/test/net/ftp/test_ftp.rb:760]:
<"STAT\r"> expected but was
<"STAT\r\n">.

これは、受信側で BasicSocket#recv システムコールをそのまま使っているが、
バッファリングはOSや環境に依存するのが原因と思われます。
Linuxでは最後の"\n"だけ別の塊として受信しますが、Solarisでは全部を同時に受信するようです。

SO_OOBINLINE を指定したのだから、recv システムコールを直接使わなくても、gets を使えば十分と考えられます。

まとめると、以下のパッチにより、ErrorおよびFailureは出なくなりました。

Index: test/net/ftp/test_ftp.rb
===================================================================
--- test/net/ftp/test_ftp.rb    (revision 49774)
+++ test/net/ftp/test_ftp.rb    (working copy)
@@ -711,7 +711,7 @@
       sock.print("230 Login successful.\r\n")
       commands.push(sock.gets)
       sock.print("200 Switching to Binary mode.\r\n")
-      commands.push(sock.recv(1024))
+      commands.push(sock.gets)
       sock.print("225 No transfer to ABOR.\r\n")
     }
     begin
@@ -724,7 +724,7 @@
         assert_match(/\APASS /, commands.shift)
         assert_equal("TYPE I\r\n", commands.shift)
         ftp.abort
-        assert_equal("ABOR\r", commands.shift)
+        assert_equal("ABOR\r\n", commands.shift)
         assert_equal(nil, commands.shift)
       ensure
         ftp.close if ftp
@@ -744,7 +744,7 @@
       sock.print("230 Login successful.\r\n")
       commands.push(sock.gets)
       sock.print("200 Switching to Binary mode.\r\n")
-      commands.push(sock.recv(1024))
+      commands.push(sock.gets)
       sock.print("211 End of status\r\n")
     }
     begin
@@ -757,7 +757,7 @@
         assert_match(/\APASS /, commands.shift)
         assert_equal("TYPE I\r\n", commands.shift)
         ftp.status
-        assert_equal("STAT\r", commands.shift)
+        assert_equal("STAT\r\n", commands.shift)
         assert_equal(nil, commands.shift)
       ensure
         ftp.close if ftp
@@ -856,6 +856,7 @@
       end
       sock = server.accept
       begin
+        sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 1)
         yield(sock)
         sock.shutdown(Socket::SHUT_WR)
         sock.read unless sock.eof?

Solaris, Linux にて動作を確認しました。
Windowsなどその他のOSでは未確認です。


Files

20150227-test-ftp.patch (1.61 KB) 20150227-test-ftp.patch ngoto (Naohisa Goto), 02/27/2015 03:39 PM

Updated by usa (Usaku NAKAMURA) over 5 years ago

Naohisa Goto wrote:

Solaris, Linux にて動作を確認しました。
Windowsなどその他のOSでは未確認です。

そこはまあ、入れてみればわかるのでいいんじゃないかと。
(ちなみにこの変更自体はWindowsでもたぶん問題はありません。)

#2

Updated by ngoto (Naohisa Goto) over 5 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

Applied in changeset r49800.


  • test/net/ftp/test_ftp.rb (create_ftp_server): set SO_OOBINLINE for receiving OOB data which is sended with MSG_OOB flag in portable way. [Bug #10915] [ruby-dev:48885]
  • test/net/ftp/test_ftp.rb (test_abort, test_status): use gets for receiving OOB data in portable way.

Also available in: Atom PDF