0

I have this test program

import sys

for line in sys.stdin:
    print(line.strip())

print("DONE")

if I get it to print out lines from a real device (an FTDI)

python3 demo.py < /dev/ttyUSB0

then it prints every line I send, and then when I pull out the usb cable, I see the DONE message

On the other hand if I create a fake tty with socat

socat -d -d pty,raw,echo=0,link=ttyFake pty,raw,echo=0,link=ttyFake.interface

and then user the python program to monitor the the fake device:

python3 demo.py < ttyFake

I can send it messages like this

echo test >> ttyFake.interface

and they get printed

but if I stop the socat process with SIGINT or SIGTERM I get something like this:

$ python3 demo.py < ttyFake
test
Traceback (most recent call last):
  File "~/serial-experiment/demo.py", line 3, in <module>
    for line in sys.stdin:
OSError: [Errno 5] Input/output error

I have also tried this with no luck:

$ echo -ne '\004' >> ttyFake.interface # send ^D

Is there any way to make socat simulate the unplugging behaviour? Do I just need a better way to send a ^D?

Subquestion: I don't really know if ^D is what the process detects in stdin to determine that input has finished, or just what you send to your terminal emulator to end the input.

2
  • shouldn't the cable unplugging generate an error?
    – jsotola
    Oct 27, 2023 at 16:36
  • no it doesn't - maybe I am solving the wrong problem. I should be working on making unplugging break it just like the tests do. My real program is lua - I just used python for the minimal example. so I don't think python is the problem. maybe the FTDI driver
    – Alex028502
    Oct 27, 2023 at 17:34

1 Answer 1

0

I have a workaround to make my test work. This could just as easily be a part of the question - so maybe I am trying to take advantage of "Cunningham's Law" (which Cunningham himself seems to have had nothing to do with)

$ mkdir solution
$ cd solution
$ cat > demo.py
import sys

for line in sys.stdin:
    print(line.strip())

print("DONE")
$ # make sure you ctrl+D at then end
$ mkfifo ttyConnector # DIFFERENT FROM QUESTION
$ socat -d -d pty,raw,echo=0,link=ttyFake pty,raw,echo=0,link=ttyFake.interface

new terminal:

$ cd solution
$ cat > ttyConnector < ttyFake # DIFFERENT FROM QUESTION

new terminal: (let's call this one app terminal)

$ cd solution
$ python3 demo.py < ttyConnector # DIFFERENT FROM QUESTION

new terminal:

$ cd solution
$ cat > ttyFake.interface
test
test
test
$ # make sure you ctrl+D at then end

(make sure you ctrlpython3 demo.py < ttyConnector+D at the end)

now take a look at app terminal

$ python3 demo.py < ttyConnector
test
test
test

even though the we ended the transmission to the pty, the fifo is still open

but go back to the socat terminal and ctrl+c, and look at the app terminal

$ python3 demo.py < ttyConnector
test
test
test
DONE

So it seems to I can simulate the behaviour of unplugging the FTDI from USB by passing everything through a fifo and killing socat. I have two programs connected together with a pty pair (the program that simulates the FTDI device and the the program that listens). I can use this workaround (for now) because the listening program only opens its end of the pty pair for reading, while the fake device reads and writes, and the test itself writes.

            /--> P --> FIFO --> demo.py
FAKE DEVICE      T
            \<-- Y <-- TEST

If I only needed one way communication on both ends, I would just skip socat, and just use a fifo.

FAKE DEVICE --> FIFO --> demo.py

and if I needed full two way communication, I would need the real solution, which I don't know yet.

            /--> P -->\ 
FAKE DEVICE      T      demo.py
            \<-- Y <--/

because if demo.py expected to read and write the same path, it wouldn't be so easy to insert two fifos

So I am still hoping to find out what I need to do to close the PTY nicely without this workaround.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .