parent: raise a descriptive error when openpty fails.

pull/372/head
David Wilson 6 years ago
parent 2647f73501
commit c4c6ae88a4

@ -78,6 +78,13 @@ try:
except: except:
SC_OPEN_MAX = 1024 SC_OPEN_MAX = 1024
OPENPTY_MSG = (
"Failed to create a PTY: %s. It is likely the maximum number of PTYs has "
"been reached. Consider increasing the 'kern.tty.ptmx_max' sysctl on OS "
"X, the 'kernel.pty.max' sysctl on Linux, or modifying your configuration "
"to avoid PTY use."
)
def get_log_level(): def get_log_level():
return (LOG.level or logging.getLogger().level or logging.INFO) return (LOG.level or logging.getLogger().level or logging.INFO)
@ -254,6 +261,22 @@ def _acquire_controlling_tty():
fcntl.ioctl(2, termios.TIOCSCTTY) fcntl.ioctl(2, termios.TIOCSCTTY)
def openpty():
"""
Call :func:`os.openpty`, raising a descriptive error if the call fails.
:raises mitogen.core.StreamError:
Creating a PTY failed.
:returns:
See :func`os.openpty`.
"""
try:
return os.openpty()
except OSError:
e = sys.exc_info()[1]
raise mitogen.core.StreamError(OPENPTY_MSG, e)
def tty_create_child(args): def tty_create_child(args):
""" """
Return a file descriptor connected to the master end of a pseudo-terminal, Return a file descriptor connected to the master end of a pseudo-terminal,
@ -268,7 +291,7 @@ def tty_create_child(args):
:returns: :returns:
`(pid, tty_fd, None)` `(pid, tty_fd, None)`
""" """
master_fd, slave_fd = os.openpty() master_fd, slave_fd = openpty()
mitogen.core.set_block(slave_fd) mitogen.core.set_block(slave_fd)
disable_echo(master_fd) disable_echo(master_fd)
disable_echo(slave_fd) disable_echo(slave_fd)
@ -300,7 +323,7 @@ def hybrid_tty_create_child(args):
:returns: :returns:
`(pid, socketpair_fd, tty_fd)` `(pid, socketpair_fd, tty_fd)`
""" """
master_fd, slave_fd = os.openpty() master_fd, slave_fd = openpty()
parentfp, childfp = create_socketpair() parentfp, childfp = create_socketpair()
mitogen.core.set_block(slave_fd) mitogen.core.set_block(slave_fd)

@ -121,6 +121,25 @@ class ContextTest(testlib.RouterMixin, unittest2.TestCase):
self.assertRaises(OSError, lambda: os.kill(pid, 0)) self.assertRaises(OSError, lambda: os.kill(pid, 0))
class OpenPtyTest(testlib.TestCase):
func = staticmethod(mitogen.parent.openpty)
def test_pty_returned(self):
master_fd, slave_fd = self.func()
self.assertTrue(isinstance(master_fd, int))
self.assertTrue(isinstance(slave_fd, int))
os.close(master_fd)
os.close(slave_fd)
@mock.patch('os.openpty')
def test_max_reached(self, openpty):
openpty.side_effect = OSError(errno.ENXIO)
e = self.assertRaises(mitogen.core.StreamError,
lambda: self.func())
msg = mitogen.parent.OPENPTY_MSG % (openpty.side_effect,)
self.assertEquals(e.args[0], msg)
class TtyCreateChildTest(unittest2.TestCase): class TtyCreateChildTest(unittest2.TestCase):
func = staticmethod(mitogen.parent.tty_create_child) func = staticmethod(mitogen.parent.tty_create_child)

Loading…
Cancel
Save