Project

General

Profile

Bug #14786

PTY duplicated "\r" problem on Solaris

Added by ngoto (Naohisa Goto) about 1 year ago. Updated about 1 year ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-dev:50552]

Description

Solaris 10 にて、コンパイル時のオプション、実行時の環境やそれらの組み合わせにより、
make test-all にて以下の Failure や Error が出る場合があります。
(r63444 にて確認)

TestPTYTestIO_ConsoleのFailureを見るとわかりやすいですが、
PTYが返す文字列に余計な "\r" が付加されています。
TestRubyOptions のエラーは、余計な "\r" が無いことを仮定して子プロセスをPTY内で走らせているために発生したようです。

PerlモジュールIPC-Runにて、Solaris上のPTYにおける同様の現象の発生が報告されていました。
https://rt.cpan.org/Public/Bug/Display.html?id=20105#txn-1306129
このPerlモジュールでは、"\r" を複数許すようなパターンを使うことで回避したようです。

Solaris以外でも "\r\r" になる現象の発生があるようです。
Pythonの Lib/test/test_pty.py には、OSF/1 (Tru64) にて発生しているようなコメントが書かれています。
https://github.com/python/cpython/blob/825aab95fde959541859383f8ea7e7854ebfd49f/Lib/test/test_pty.py#L48

    # OSF/1 (Tru64) apparently turns \n into \r\r\n.
    if data.endswith(b'\r\r\n'):
        return data.replace(b'\r\r\n', b'\n')

以下が make test-all 時のFailureやErrorの抜粋です。

  2) Failure:
TestIO_Console#test_cooked [/XXXXXXXX-63444/test/io/console/test_io_console.rb:93]:
<"def\r\n"> expected but was
<"def\r\r\n">.

  3) Failure:
TestIO_Console#test_noecho2 [/XXXXXXXX-63444/test/io/console/test_io_console.rb:130]:
<"a\r\n" + "b\r\n"> expected but was
<"a\r\n" + "a\r\r\n" + "b\r\r">.

  4) Failure:
TestIO_Console#test_raw [/XXXXXXXX-63444/test/io/console/test_io_console.rb:18]:
<"abc\r\n"> expected but was
<"abc\r\r\n">.

  5) Failure:
TestIO_Console#test_setecho2 [/XXXXXXXX-63444/test/io/console/test_io_console.rb:168]:
<"a\r\n" + "b\r\n"> expected but was
<"a\r\n" + "a\r\r\n" + "b\r\r">.

  6) Failure:
TestPTY#test_argv0 [/XXXXXXXX-63444/test/test_pty.rb:58]:
<"bar\r\n"> expected but was
<"bar\r\r\n">.

  7) Failure:
TestPTY#test_commandline [/XXXXXXXX-63444/test/test_pty.rb:44]:
<"foo\r\n"> expected but was
<"foo\r\r\n">.

  8) Failure:
TestPTY#test_open [/XXXXXXXX-63444/test/test_pty.rb:131]:
<"foo"> expected but was
<"foo\r">.

  9) Failure:
TestPTY#test_spawn_with_block [/XXXXXXXX-63444/test/test_pty.rb:29]:
<"b\r\n"> expected but was
<"b\r\r\n">.

 10) Failure:
TestPTY#test_spawn_without_block [/XXXXXXXX-63444/test/test_pty.rb:19]:
<"a\r\n"> expected but was
<"a\r\r\n">.

 11) Failure:
TestRubyOptions#test_script_from_stdin [/XXXXXXXX-63444/test/ruby/test_rubyoptions.rb:775]:
[ruby-dev:37798].
Exception raised:
<#<Timeout::Error: execution expired>>.

 12) Failure:
TestRubyOptions#test_script_from_stdin [/XXXXXXXX-63444/test/lib/zombie_hunter.rb:9]:
Expected [[11281, #<Process::Status: pid 11281 exit 0>]] to be empty.

Associated revisions

Revision 26cbe46e
Added by ngoto (Naohisa Goto) about 1 year ago

ext/pty/pty.c: I_FIND before I_PUSH if possible

  • ext/pty/pty.c: Check whether each STREAMS module is already pushed or not by using I_FIND ioctl call, before pushing it by using I_PUSH. Solved test failure on Solaris. On a Solaris 10 machine, ioctl I_PUSH "ldterm" twice was the cause of duplicated "\r". [Bug #14786] [ruby-dev:50552]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 63495
Added by ngoto (Naohisa Goto) about 1 year ago

ext/pty/pty.c: I_FIND before I_PUSH if possible

  • ext/pty/pty.c: Check whether each STREAMS module is already pushed or not by using I_FIND ioctl call, before pushing it by using I_PUSH. Solved test failure on Solaris. On a Solaris 10 machine, ioctl I_PUSH "ldterm" twice was the cause of duplicated "\r". [Bug #14786] [ruby-dev:50552]

Revision 63495
Added by ngoto (Naohisa Goto) about 1 year ago

ext/pty/pty.c: I_FIND before I_PUSH if possible

  • ext/pty/pty.c: Check whether each STREAMS module is already pushed or not by using I_FIND ioctl call, before pushing it by using I_PUSH. Solved test failure on Solaris. On a Solaris 10 machine, ioctl I_PUSH "ldterm" twice was the cause of duplicated "\r". [Bug #14786] [ruby-dev:50552]

History

Updated by ngoto (Naohisa Goto) about 1 year ago

ext/pty/pty.c にて、以下のように STREAMS モジュールを挿入しています。

    if (ioctl(slavefd, I_PUSH, "ptem") == -1) goto error;
    if (ioctl(slavefd, I_PUSH, "ldterm") == -1) goto error;
    if (ioctl(slavefd, I_PUSH, "ttcompat") == -1) goto error;

しかし、環境によっては、最初から ptem, ldterm, ttcompat の各モジュールが挿入済の場合もあるようです。

そこで、以下のように、I_FIND にて挿入済か否かをチェックして、0を返した=未挿入の場合だけ挿入するようにしたら、少なくとも私の手元のSolarisでは、Failure/Errorが出なくなりました。

どうやら、モジュールの二重挿入がダメだったようです。私の環境では、ldterm の二重挿入が "\r" が重複した直接の原因でした。

    if (!ioctl(slavefd, I_FIND, "ptem")) if (ioctl(slavefd, I_PUSH, "ptem") == -1) goto error;
    if (!ioctl(slavefd, I_FIND, "ldterm")) if (ioctl(slavefd, I_PUSH, "ldterm") == -1) goto error;
    if (!ioctl(slavefd, I_FIND, "ttcompat")) if (ioctl(slavefd, I_PUSH, "ttcompat") == -1) goto error;

なお、実際には、I_FIND 時のエラー処理も行う必要があります。

#2

Updated by ngoto (Naohisa Goto) about 1 year ago

  • Status changed from Open to Closed

Applied in changeset trunk|r63495.


ext/pty/pty.c: I_FIND before I_PUSH if possible

  • ext/pty/pty.c: Check whether each STREAMS module is already pushed or not by using I_FIND ioctl call, before pushing it by using I_PUSH. Solved test failure on Solaris. On a Solaris 10 machine, ioctl I_PUSH "ldterm" twice was the cause of duplicated "\r". [Bug #14786] [ruby-dev:50552]

Also available in: Atom PDF