dupterm on Unix blocks (slot 1) / replicates to stdout (slot 0)
Port, board and/or hardware
Unix
MicroPython version
MicroPython v1.27.0
Reproduction
- compile the Unix port with
#define MICROPY_PY_OS_DUPTERM (2) - run the binary
- import the following test module
import io
import os
CHAN=1
class F(io.IOBase):
def __init__(self):
self.d=bytearray(b"2*21\n")
def write(self, buf):
return len(buf)
def read(self,n):
if not self.d:
return None
if n < (ld := len(self.d)):
res = self.d[:n]
self.d[:n] = b''
else:
res = self.d
self.d = b''
os.dupterm(None,CHAN) # we're done
return res
def ioctl(self, req, flags):
if req == 3:
if self.d:
return flags & 1
return 0
return None
buf = F()
os.dupterm(buf,CHAN)
Expected behaviour
>>> import duptest
>>> 2*21
42
>>>
Note that the 2*21 part isn't typed by me.
Observed behaviour
>>> import duptest
>>>
Additional Information
strace shows that micropython blocks on reading standard input.
Using CHAN=0 "fixes" the problem but exhibits a different one: it sends output to both stdout and the dupterm'd IOBase subclass, but reads only from the latter. This is somewhat counter-intuitive and not what I'd like to happen.
Code of Conduct
Yes, I agree
ports/unix: Add full uos.dupterm support.
The unix port currently supports a very limited uos.dupterm implementation.
It can only replace stdin and/or duplicate stdout.
When using uos.dupterm to replace slot 0 it does not return a handle to the existing (posix stdio) stream.
This PR resolves these issues, preferring to use dupterm for all stdio on unix when MICROPY_PY_OS_DUPTERM=1 is configured in the build.
With this change simple modification of the output stream is possible, for example to format logging messaging with a basic timestamp
stdio = None
class logger:
def write(self, buf):
global stdio
stdio.write(str(utime.time()))
stdio.write(" | ")
stdio.write(buf)
stdio = uos.dupterm(logger(), 0)