Skip to content

gh-119273: Don't run test_ioctl in a process group #119275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 29, 2024

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented May 20, 2024

Python test runner no longer runs tests using TTY (ex: test_ioctl) in a process group (using setsid()). Previously, tests using TTY were skipped.

Python test runner no longer runs tests using TTY (ex: test_ioctl) in
a process group (using setsid()). Previously, tests using TTY were
skipped.
@vstinner
Copy link
Member Author

Without this change, the test is skipped:

$ ./python -m test test_ioctl -j1
(...)
test_ioctl skipped -- Unable to open /dev/tty

With the change, the test is no longer skipped:

$ ./python -m test test_ioctl -j1
(...)
Result: SUCCESS

Copy link
Member

@gpshead gpshead left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. While I wish there were a better way to avoid maintaining a special case list within libregrtest itself, the implementation of how not to use a process group is the same even if we gain that more direct ability instead of a far removed list in the future.

@@ -14,6 +14,9 @@


USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg"))
NEED_TTY = set('''
test_ioctl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a couple of other tests that skip some of the test methods/classes when stdout is not a tty: test_builtin, test_curses, test_os, test_shutil at least, from a quick grep. I'm not sure it's going to be maintainable to keep a list like this up to date...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option would be to move "tty" tests in separated test files and disable setsid() if the test name contains _tty. For example, we already do that with GUI tests (ex: test_ttk and test_ttk_textonly).

@vstinner
Copy link
Member Author

Test on fork+setsid:

import io
import os

def check_tty(context):
    try:
        f = io.FileIO("/dev/tty", "a")
        tty = f.isatty()
        f.close()
    except OSError as exc:
        print(f"{context}: Is a TTY? {exc}")
    else:
        print(f"{context}: Is a TTY? {tty}")

check_tty("parent")
pid = os.fork()
if pid:
    os.waitpid(pid, 0)
else:
    os.setsid()
    check_tty("child after fork+setsid")

Result on Linux:

parent: Is a TTY? True
child after fork+setsid: Is a TTY? [Errno 6] No such device or address: '/dev/tty'

The child process cannot open /dev/tty after fork+setsid.

@vstinner
Copy link
Member Author

vstinner commented May 23, 2024

The following tests contains the word tty (outside comments). I checked if they are skipped when run in a worker process.

Skipped tests:

  • test_builtin: always skipped. test_input_tty*() tests need a TTY and requires that readline is not loaded.
  • test_fileio: always skipped silently. testAbles()
  • test_ioctl: always skipped (whole file).
  • test_shutil: always skipped. test_shutil.test_stty_match() requires sys.__stdout__ to be a TTY to run the command stty size. When using worker process, stdout is a pipe and not a TTY.

Tests not skipped (ok):

  • test_curses
  • test_file
  • test_getpass: accessing /dev/tty uses a mock
  • test_os: stdin is a TTY.
  • test_pty
  • test_readline
  • test_sundry
  • test_threading
  • test_tty: use os.openpty()
  • test_utf8_mode

@vstinner
Copy link
Member Author

Using os.openpty() is fine with fork+setsid:

import io
import os

def check_tty(context):
    try:
        parent_fd, child_fd = os.openpty()
        tty = os.isatty(parent_fd)
        os.close(parent_fd)
        os.close(child_fd)
    except OSError as exc:
        print(f"{context}: Is a TTY? {exc}")
    else:
        print(f"{context}: Is a TTY? {tty}")

check_tty("parent")
pid = os.fork()
if pid:
    os.waitpid(pid, 0)
else:
    os.setsid()
    check_tty("child after fork+setsid")

Output:

parent: Is a TTY? True
child after fork+setsid: Is a TTY? True

@vstinner vstinner marked this pull request as ready for review May 29, 2024 12:43
@vstinner vstinner enabled auto-merge (squash) May 29, 2024 12:44
@vstinner vstinner merged commit 1f481fd into python:main May 29, 2024
44 checks passed
@vstinner vstinner deleted the regrtest_tty branch May 29, 2024 12:44
@vstinner
Copy link
Member Author

I merged this PR as it is. I will prepare a following PR to handle test_builtin, test_fileio and test_shutil.

@vstinner
Copy link
Member Author

test_builtin: always skipped. test_input_tty*() tests need a TTY and requires that readline is not loaded.
test_shutil: always skipped. test_shutil.test_stty_match() requires sys.stdout to be a TTY to run the command stty size. When using worker process, stdout is a pipe and not a TTY.

Sadly, these two tests need stdout to be a TTY. It's only doable if tests are run sequentially.

test_fileio: always skipped silently. testAbles()

Well, it's just a subset of a minor test. I don't think that it's worth it to create a whole test file just for a few lines.

@vstinner
Copy link
Member Author

Follow-up: I created issue gh-119727: Add --sequentially option to regrtest to always run tests sequentially (ignore -jN option).

noahbkim pushed a commit to hudson-trading/cpython that referenced this pull request Jul 11, 2024
Python test runner no longer runs tests using TTY (ex: test_ioctl) in
a process group (using setsid()). Previously, tests using TTY were
skipped.
estyxx pushed a commit to estyxx/cpython that referenced this pull request Jul 17, 2024
Python test runner no longer runs tests using TTY (ex: test_ioctl) in
a process group (using setsid()). Previously, tests using TTY were
skipped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants