-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
read1 in cbreak mode returns 0x0D (instead of 0x0A) when <enter> is entered. #114328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Linux and MacOs require/define <enter> (LF) mapped to 0x0A. This cannot be correct in my opinion (user-visible or not). See https://en.wikipedia.org/wiki/Newline (Unicode is similar.) |
The change feels accidental given that it isn't mentioned anywhere (including in the discussion on the PR and issue) |
I'm assuming it's caused by these opening lines in the new def cfmakecbreak(mode):
"""Make termios mode cbreak."""
# Do not map CR to NL on input.
mode[IFLAG] &= ~(ICRNL)
... @8vasu - any thoughts? |
To restore the behavior and retain compatibility we could presumably just remove that ICRNL clearing. It feels worth looking things up to reference where in what standard (posix?) this intent is defined one way or another in a comment. presumably: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html |
The posix doc is a bit hard to reason about w.r.t. this as it does not mention mode names as used in stty... But is what underlies all these things. The Linux stty man page doesn't explicitly mention There appear to be other opinions on this, AIX's "understanding terminals" docs explicitly say Yet the very name So I agree we should just remove the explicit clearing of ICRNL as a bugfix for this 3.12 code (and note this in our docs). I believe that means we just inherit the current setting for that flag, which is what our previous behavior had long been. |
The FreeBSD and macOS stty man pages appear to agree with my reading of "icrnl shouldn't be touched for cbreak". |
CR -> NL mapping should be inherited in cbreak mode as OSes do not specify altering it as part of their `stty` cbreak mode definition.
Question: this issue should be covered by a specific test I think? |
To my knowledge, the cbreak/rare mode is defined neither in the POSIX manual for stty (https://pubs.opengroup.org/onlinepubs/9699919799/) nor in the POSIX General Terminal Interface. I think the authoritative source in this case is X/Open Curses, Issue 7 (https://pubs.opengroup.org/onlinepubs/9699909599/toc.pdf). A quick search though the pdf reveals the following definition of cbreak mode, which posits clearing
For an example implementation, please refer to the source of In my opinion, the functions in |
Following the standards is of course the way to go, but cbreak seems not to be fully defined.
Also from the macOS stty manpage I get:
If I combine the two, I get that ICRNL must be set when cbreak is cleared (but not specifically cleared when cbreak is set) |
It is not going to be fully defined in the standard. Only what it must do will be specified; rest can be implementation-specific as long as it is consistent with what it must do. Expect severe fragmentation and platform-specific chaos if you deviate from the standard (which is what the Since in this case the original behavior of Also, maybe we should include a link to the relevant section of X/Open Curses, Issue 7 or The Single UNIX Specification, Version 4 in |
That makes sense. I agree especially about the source comment. |
thanks for the additional research. Agreed with "keep compatibility with prior pythons" in terms of setcbreak behavior. tty.py logic on these hasn't changed in 30 years and there is no trail to indicate why the current values were chosen - they no doubt worked for whatever Steen Lumholt was trying to do at the time on a very old OS. They appear to match what Linux and macOS I've updated my draft PR with better documentation to along with the behavior restoration. Testing actual behaviors of the stty command on Linux and macOS: You can take the example program up top and change the tty.setcbreak call to Reading some of the linked docs, the "c" in "cbreak" might stand for "Cooked" rather than "Canonical" as I had earlier assumed? Regardless of what the presumed abbreviation might have meant at some ancient point in time, it doesn't matter. We've found the behavior users expect. |
I suppose a question about |
I sent a message to GNU coreutils and to FreeBSD about stty. I think as usual macos is using the FreeBSD stty. I suspect that since the standard linked above pertains to Curses and not to stty, no implementation of stty needs to follow it. However, it will still be interesting to see their reply. |
Here is the conversation with GNU Coreutils: https://lists.gnu.org/archive/html/coreutils/2024-01/msg00016.html Therefore, the rigorous conclusion is this: we should do exactly as @gpshead suggested. At the same time, I will try to add a |
That PR looks good. I agree that we should restore the previous behaviour. That's what Python has done for a long time and there is no strong reason to change the behaviour. |
The terminal CR -> NL mapping setting should be inherited in cbreak mode as OSes do not specify altering it as part of their stty cbreak mode definition.
) The terminal CR -> NL mapping setting should be inherited in cbreak mode as OSes do not specify altering it as part of their stty cbreak mode definition. (cherry picked from commit fd49e22) Co-authored-by: Gregory P. Smith <greg@krypto.org>
Thanks for the good report, reproducer, and discussions! Fixed in main, the 3.12 backport is set to automerge. |
The terminal CR -> NL mapping setting should be inherited in cbreak mode as OSes do not specify altering it as part of their stty cbreak mode definition.
The terminal CR -> NL mapping setting should be inherited in cbreak mode as OSes do not specify altering it as part of their stty cbreak mode definition.
The terminal CR -> NL mapping setting should be inherited in cbreak mode as OSes do not specify altering it as part of their stty cbreak mode definition.
Bug report
Bug description:
A read1 of 'stdin' in cbreak mode returns 0x0D (instead of 0x0A) when <enter> is entered.
That is for Python version 3.12.1, version 3.11.6 returns 0x0A.
The following code demonstrates this. When run enter <enter>.
CPython versions tested on:
3.11, 3.12
Operating systems tested on:
Linux, macOS
Linked PRs
The text was updated successfully, but these errors were encountered: