Skip to content

StdIn Not Handled in ExecuteProcess? #735

Closed
@mwcondino

Description

@mwcondino

Bug report

Required Info:

  • Operating System:
    • Ubuntu 22.04
  • Installation type:
    • binaries
  • Version or commit hash:
    • humble, ros-humble-launch=1.0.3-1jammy.20221019.125253. Also checked on 1.0.4-1jammy.20230718.195748
  • DDS implementation:
    • Fast-RTPS

Steps to reproduce issue

Run this file with ros2 launch ./test.launch.py

test.launch.py:

"""Launch file for testing."""


import asyncio as aio
import contextlib
import sys
import termios

from launch import LaunchDescription
from launch.actions import ExecuteProcess, OpaqueCoroutine

from launch.events.process import ProcessStdin

# From https://stackoverflow.com/questions/35223896/listen-to-keypress-with-asyncio
@contextlib.contextmanager
def raw_mode(file):
    old_attrs = termios.tcgetattr(file.fileno())
    new_attrs = old_attrs[:]
    new_attrs[3] = new_attrs[3] & ~(termios.ECHO | termios.ICANON)
    try:
        termios.tcsetattr(file.fileno(), termios.TCSADRAIN, new_attrs)
        yield
    finally:
        termios.tcsetattr(file.fileno(), termios.TCSADRAIN, old_attrs)


# Function to emit an event when a key is pressed
async def read_char_from_stdin(_launch_context, action=None):
    with raw_mode(sys.stdin):
        reader = aio.StreamReader()
        loop = aio.get_event_loop()
        await loop.connect_read_pipe(lambda: aio.StreamReaderProtocol(reader), sys.stdin)

        while not reader.at_eof():
            ch = await reader.read(1)
            # '' means EOF, chr(4) means EOT (sent by CTRL+D on UNIX terminals)
            if not ch or ord(ch) <= 4:
                break
            print(f'Got: {ch!r}')

            pid = action.process_details['pid']
            await _launch_context.emit_event(
                event=ProcessStdin(
                    text=ch, action=action, name=action.name, cmd=action.cmd,
                    cwd=action.cwd, env=action.env, pid=pid))


def generate_launch_description():
    """Generate the args and items to launch."""
    # Create the launch description and populate
    ld = LaunchDescription()

    cmd_list = ['ros2', 'bag', 'play', 'test_bag']

    bag_runner = ExecuteProcess(
        cmd=cmd_list,
        emulate_tty=True,
    )

    ld.add_action(OpaqueCoroutine(coroutine=read_char_from_stdin, kwargs={'action': bag_runner}))

    ld.add_action(bag_runner)

    return ld

Once that is running, press space - the expected behavior is that the space character would be forwarded to the ExecuteProcess action which is playing back the bag (any bag will work for this test, so long as the name matches up).

However, when I press space (or really any character), I get this warning:

[WARNING] [ros2-1]: in ExecuteProcess('140309050411568').__on_process_stdin_event()

Expected behavior

The ProcessStdin event should forward data to the matching process.

Actual behavior

It looks like there's just a warning message. From looking into the code here, it appears as if the function is not really implemented, unless I'm missing something.

I think that ExecuteProcess may need some updating to correctly pipe data passed into the __on_process_stdin_event function to the underlying subprocess.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions