Skip to content

Make 'run_cmd' operate without universal newlines#462

Merged
lsf37 merged 1 commit into
seL4:masterfrom
au-ts:julia/onlcr-handling
May 26, 2026
Merged

Make 'run_cmd' operate without universal newlines#462
lsf37 merged 1 commit into
seL4:masterfrom
au-ts:julia/onlcr-handling

Conversation

@midnightveil
Copy link
Copy Markdown
Contributor

In 'text' mode (an alias for universal_newlines), Python converts all \r\n sequences into just \n, under the expectation that on Linux it is not necessary to explicit emit a carriage return (and that this would be consistent with other platforms where it does similar).

However, this is not always true: if stty -onlcr is set, then newline (\n) does not automatically emit a carriage return (\r). Our machine queue scripts (linked below) explicitly set -onlcr, so a \r is also needed for \n to behave as expected. But with universal newlines on, the \r emitted by the other end of mq.sh ends up being stripped.

https://github.com/seL4/machine_queue/blob/master/scripts/remote#L16

We turn off 'text'/'universal_newlines' mode, leaving the output in raw binary (which also necessitates disabling line buffering as python does not support that, and so we disable all buffering entirely); then we decode() to text as necessary for the lines return-value, and print binary to our stdout.

This is necessary to make the local CI runner I added for microkit to emit output that does not perform the staircase output when \r is not being emitted.

@midnightveil midnightveil requested a review from lsf37 as a code owner April 23, 2026 01:28
@midnightveil
Copy link
Copy Markdown
Contributor Author

OK, I'm not sure if this was an issue beforehand, but it is definitely an issue now:

If we start to get output that looks like:

=> go ${loadaddr}
go ${loadaddr}
## Starting application at 0x80280000 ...
LDR|INFO|CPU0: CurrentEL=UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU [continues for at least another 4k chars

Then Python exits with

Traceback (most recent call last):
  File "/home/julia/ts/microkit-mmu/ci-actions/scripts/../microkit-hw-run/build.py", line 205, in <module>
    sys.exit(run_builds(builds, hw_run))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 885, in run_builds
    results[run_fun(manifest_dir, build)].append(build.name)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/julia/ts/microkit-mmu/ci-actions/scripts/../microkit-hw-run/build.py", line 110, in hw_run
    return run_build_script(
           ^^^^^^^^^^^^^^^^^
  File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 562, in run_build_script
    result, output = run_cmd(line, run, output)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 461, in run_cmd
    return cmd(run, prev_output)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 409, in wrapped_cmd
    result, output = run_cmd(cmd, run, prev_output)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 445, in run_cmd
    sys.stdout.buffer.write(line)
BlockingIOError: [Errno 11] write could not complete without blocking

@midnightveil
Copy link
Copy Markdown
Contributor Author

midnightveil commented Apr 23, 2026

OK, no, this issue already existed beforehand:

log
+++ time mq.sh run -c hello, world -s tqma -d 30 -t -1 -w 8 -l TQMA8XQP1GB_debug -n -k microkit-locally-local-local-0 -f /home/julia/ts/microkit-mmu/test-ci-build/TQMA8XQP1GB_debug.loader.img
Lock acquired, we are allowed to run
pxelinux=False
              copied '/tmp/tmp.0ujqvUt8nx' -> '/tftpboot/tqma/sel4-image'
                                                                         removed '/tmp/tmp.0ujqvUt8nx'
                                                                                                      co
                                                                                                        ^Eco

                                                                                                            [Enter `^Ec?' for help]

                                                                                                                                   [up]

                                                                                                                                       Rebooting tqma and loading image: /tmp/tmp.0ujqvUt8nx



                                                                                                                                                                                            U-Boot SPL 2020.04-tq+ge52fed3d (Dec 16 2020 - 17:20:31 +0000)


                 Normal Boot


                            Trying to boot from MMC2_2


                                                      Primary set selected


                                                                          Load image from MMC/SD 0x58400








                                                                                                        U-Boot 2020.04-tq+ge52fed3d (Dec 16 2020 - 17:20:31 +0000)





                                                                                                                                                                  CPU:   NXP i.MX8QXP RevC A35 at 1200 MHz





                                                                                                                                                                                                          Model: TQ-Systems i.MX8QXP TQMa8XQP on MBa8Xx


              Boot:  SD1


                        Board: TQMa8XQP on a MBa8Xx


                                                   PMIC0: ID 0x40 REV 0x31 PROG_ID 0x0000


                                                                                         SCU:   6f9d593628cc


                                                                                                            DRAM:  1022 MiB


                                                                                                                           SDRAM: 1024 MiB DDR3L ECC - @ 928 MHz (RPA 0300)





                                                                                                                                                                           MMC:   FSL_SDHC: 0, FSL_SDHC: 1


                                                                                                                                                                                                          Loading Environment from MMC... *** Warning - bad CRC, using default environment





                                                 In:    serial@5a070000


                                                                       Out:   serial@5a070000


                                                                                             Err:   serial@5a070000


                                                                                                                   TQMa8XQP EEPROM:


                                                                                                                                     ID: TQMa8XQP-P1.0201


                                                                                                                                                           SN: 73915514


                                                                                                                                                                         MAC: 00:d0:93:4f:b9:c3


                                                                                                                                                                                               Net:


                                                                                                                                                                                                   Warning: ethernet@5b040000 using MAC address from ROM


               eth0: ethernet@5b040000Get shared mii bus on ethernet@5b050000





                                                                             Warning: ethernet@5b050000 using MAC address from ROM


                                                                                                                                  , eth1: ethernet@5b050000


                                                                                                                                                           Normal Boot


                                                                                                                                                                      Hit any key to stop autoboot:  3
                                                                                                                                                                                                    0


                                                                                                                                                                                                     =>


                                                                                                                                                                                                       => dhcp
                                                                                                                                                                                                              dhcp


                                                                                                                                                                                                                  ethernet@5b040000 Waiting for PHY auto negotiation to complete..... done


                                                 BOOTP broadcast 1


                                                                  BOOTP broadcast 2


                                                                                   BOOTP broadcast 3


                                                                                                    BOOTP broadcast 4


                                                                                                                     BOOTP broadcast 5


                                                                                                                                      DHCP client bound to address 172.16.44.176 (3768 ms)


                                                                                                                                                                                          Using ethernet@5b040000 device


                                                                                                                                                                                                                        TFTP from server 172.16.0.2; our IP address is 172.16.44.176


                                           Filename '/tqma/sel4-image'.


                                                                       Load address: 0x80280000


                                                                                               Loading: #################################################################


                                                                                                                                                                                 #################################################################


                 ######################################################


                                                                         10.3 MiB/s


                                                                                   done


                                                                                       Bytes transferred = 2699204 (292fc4 hex)


                                                                                                                               => go ${loadaddr}
                                                                                                                                                go ${loadaddr}


                                                                                                                                                              ## Starting application at 0x80280000 ...


                                                                                                                                                                                                       LDR|INFO|CPU0: CurrentEL=UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU [ a few thousand more characters] UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUTraceback (most recent call last):
                                                                                                                                                                                                        File "/home/julia/ts/microkit-mmu/ci-actions/scripts/../microkit-hw-run/build.py", line 205, in <module>
                                                                           sys.exit(run_builds(builds, hw_run))
                                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                                                                                                                        File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 878, in run_builds
                  results[run_fun(manifest_dir, build)].append(build.name)
                                                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                                                                                    File "/home/julia/ts/microkit-mmu/ci-actions/scripts/../microkit-hw-run/build.py", line 110, in hw_run
                                                                                                                                                                                                                              return run_build_script(
                        ^^^^^^^^^^^^^^^^^
                                           File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 558, in run_build_script
                                                                                                                                                    result, output = run_cmd(line, run, output)
                                                                                                                                                                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
       File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 457, in run_cmd
                                                                                                       return cmd(run, prev_output)
                                                                                                                                              ^^^^^^^^^^^^^^^^^^^^^
                                                                                                                                                                     File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 409, in wrapped_cmd
                                result, output = run_cmd(cmd, run, prev_output)
                                                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                                                                                                    File "/home/julia/ts/microkit-mmu/ci-actions/seL4-platforms/builds.py", line 441, in run_cmd
                                                                                                                                                                                                                                    print(line)
      BlockingIOError: [Errno 11] write could not complete without blocking
                                                                           ⏎                  

So this is fine then, though we should probably fix it.

@lsf37 lsf37 added the bug Something isn't working label Apr 30, 2026
In 'text' mode (an alias for universal_newlines), Python converts
all \r\n sequences into just \n, under the expectation that on Linux
it is not necessary to explicit emit a carriage return (and that this
would be consistent with other platforms where it does similar).

However, this is not always true: if `stty -onlcr` is set, then
newline (\n) does not automatically emit a carriage return (\r).
Our machine queue scripts (linked below) explicitly set `-onlcr`,
so a \r is also needed for \n to behave as expected. But with
universal newlines on, the \r emitted by the other end of `mq.sh`
ends up being stripped.

https://github.com/seL4/machine_queue/blob/master/scripts/remote#L16

We turn off 'text'/'universal_newlines' mode, leaving the output
in raw binary (which also necessitates disabling line buffering
as python does not support that, and so we disable all buffering
entirely); then we decode() to text as necessary for the lines
return-value, and print binary to our stdout.

Signed-off-by: Julia Vassiliki <julia.vassiliki@unsw.edu.au>
Copy link
Copy Markdown
Contributor

@Indanz Indanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried not setting onlcr too or only this work-around?

@midnightveil
Copy link
Copy Markdown
Contributor Author

Have you tried not setting onlcr too or only this work-around?

I haven't messed with the machine queue scripts, no. I don't know why the scripts even invoke stty tbh, I thought that SSH forwards the PTY ioctls across and conserver on the remote end does make those work. So I'm wary to change it given I don't know why it is like it is.

@lsf37 lsf37 merged commit 0a61c10 into seL4:master May 26, 2026
7 checks passed
@midnightveil midnightveil deleted the julia/onlcr-handling branch May 26, 2026 23:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants