• Maarten van der Schrieck's avatar
    ports: Fix sys.stdout.buffer.write() return value. · 3bca93b2
    Maarten van der Schrieck authored
    
    
    MicroPython code may rely on the return value of sys.stdout.buffer.write()
    to reflect the number of bytes actually written. While in most scenarios a
    write() operation is successful, there are cases where it fails, leading to
    data loss. This problem arises because, currently, write() merely returns
    the number of bytes it was supposed to write, without indication of
    failure.
    
    One scenario where write() might fail, is where USB is used and the
    receiving end doesn't read quickly enough to empty the receive buffer. In
    that case, write() on the MicroPython side can timeout, resulting in the
    loss of data without any indication, a behavior observed notably in
    communication between a Pi Pico as a client and a Linux host using the ACM
    driver.
    
    A complex issue arises with mp_hal_stdout_tx_strn() when it involves
    multiple outputs, such as USB, dupterm and hardware UART. The challenge is
    in handling cases where writing to one output is successful, but another
    fails, either fully or partially. This patch implements the following
    solution:
    
    mp_hal_stdout_tx_strn() attempts to write len bytes to all of the possible
    destinations for that data, and returns the minimum successful write
    length.
    
    The implementation of this is complicated by several factors:
    - multiple outputs may be enabled or disabled at compiled time
    - multiple outputs may be enabled or disabled at runtime
    - mp_os_dupterm_tx_strn() is one such output, optionally containing
      multiple additional outputs
    - each of these outputs may or may not be able to report success
    - each of these outputs may or may not be able to report partial writes
    
    As a result, there's no single strategy that fits all ports, necessitating
    unique logic for each instance of mp_hal_stdout_tx_strn().
    
    Note that addressing sys.stdout.write() is more complex due to its data
    modification process ("cooked" output), and it remains unchanged in this
    patch. Developers who are concerned about accurate return values from
    write operations should use sys.stdout.buffer.write().
    
    This patch might disrupt some existing code, but it's also expected to
    resolve issues, considering that the peculiar return value behavior of
    sys.stdout.buffer.write() is not well-documented and likely not widely
    known. Therefore, it's improbable that much existing code relies on the
    previous behavior.
    Signed-off-by: default avatarMaarten van der Schrieck <maarten@thingsconnected.nl>
    3bca93b2
mphal.h 3.26 KB