diff options
Diffstat (limited to 'contrib/python/podman/libs/_containers_attach.py')
-rw-r--r-- | contrib/python/podman/libs/_containers_attach.py | 98 |
1 files changed, 30 insertions, 68 deletions
diff --git a/contrib/python/podman/libs/_containers_attach.py b/contrib/python/podman/libs/_containers_attach.py index bd73542b9..df12fa998 100644 --- a/contrib/python/podman/libs/_containers_attach.py +++ b/contrib/python/podman/libs/_containers_attach.py @@ -1,16 +1,11 @@ """Exported method Container.attach().""" +import collections import fcntl -import os -import select -import signal -import socket +import logging import struct import sys import termios -import tty - -CONMON_BUFSZ = 8192 class Mixin: @@ -20,10 +15,8 @@ class Mixin: """Attach to container's PID1 stdin and stdout. stderr is ignored. + PseudoTTY work is done in start(). """ - if not self.containerrunning: - raise Exception('you can only attach to running containers') - if stdin is None: stdin = sys.stdin.fileno() @@ -41,73 +34,42 @@ class Mixin: ) # This is the control socket where resizing events are sent to conmon - ctl_socket = attach['sockets']['control_socket'] + # attach['sockets']['control_socket'] + self.pseudo_tty = collections.namedtuple( + 'PseudoTTY', + ['stdin', 'stdout', 'io_socket', 'control_socket', 'eot'])( + stdin, + stdout, + attach['sockets']['io_socket'], + attach['sockets']['control_socket'], + eot, + ) - def resize_handler(signum, frame): - """Send the new window size to conmon. + @property + def resize_handler(self): + """Send the new window size to conmon.""" - The method arguments are not used. - """ - packed = fcntl.ioctl(stdout, termios.TIOCGWINSZ, + def wrapped(signum, frame): + packed = fcntl.ioctl(self.pseudo_tty.stdout, termios.TIOCGWINSZ, struct.pack('HHHH', 0, 0, 0, 0)) rows, cols, _, _ = struct.unpack('HHHH', packed) + logging.debug('Resize window({}x{}) using {}'.format( + rows, cols, self.pseudo_tty.control_socket)) + # TODO: Need some kind of timeout in case pipe is blocked - with open(ctl_socket, 'w') as skt: + with open(self.pseudo_tty.control_socket, 'w') as skt: # send conmon window resize message skt.write('1 {} {}\n'.format(rows, cols)) - def log_handler(signum, frame): - """Send command to reopen log to conmon. + return wrapped + + @property + def log_handler(self): + """Send command to reopen log to conmon.""" - The method arguments are not used. - """ - with open(ctl_socket, 'w') as skt: + def wrapped(signum, frame): + with open(self.pseudo_tty.control_socket, 'w') as skt: # send conmon reopen log message skt.write('2\n') - try: - # save off the old settings for terminal - original_attr = termios.tcgetattr(stdout) - tty.setraw(stdin) - - # initialize containers window size - resize_handler(None, sys._getframe(0)) - - # catch any resizing events and send the resize info - # to the control fifo "socket" - signal.signal(signal.SIGWINCH, resize_handler) - - except termios.error: - original_attr = None - - try: - # TODO: socket.SOCK_SEQPACKET may not be supported in Windows - with socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) as skt: - # Prepare socket for communicating with conmon/container - skt.connect(io_socket) - skt.sendall(b'\n') - - sources = [skt, stdin] - while sources: - readable, _, _ = select.select(sources, [], []) - if skt in readable: - data = skt.recv(CONMON_BUFSZ) - if not data: - sources.remove(skt) - - # Remove source marker when writing - os.write(stdout, data[1:]) - - if stdin in readable: - data = os.read(stdin, CONMON_BUFSZ) - if not data: - sources.remove(stdin) - - skt.sendall(data) - - if eot in data: - sources.clear() - finally: - if original_attr: - termios.tcsetattr(stdout, termios.TCSADRAIN, original_attr) - signal.signal(signal.SIGWINCH, signal.SIG_DFL) + return wrapped |