haskell / haskell/unix

Incorrect terminal baud rate on glibc 2.42+

Open
#366 1 comment 0 reactions 0 assignees View on GitHub
os: Linux type: bug
Dominant language
Haskell
Stars
124
Forks
99
PR merge metrics
No merged PRs in 30d

Description

BaudRate pattern synonyms (B9600 etc.) are baked in by hsc2hs at GHC build time and become wrong when the runtime glibc differs from the build-time glibc, because glibc 2.42 changed B9600 from 13 to 9600.

### Your environment

Which OS do you use:
Ubuntu 25.10 (glibc 2.42), GHC 9.6.7 (built against glibc <= 2.41), unix-2.8.6.0

Describe your project (alternative: link to the project):
Programming a small TTY USB device (serial port at 9600 baud)

### Steps to reproduce

Use `withOutputSpeed attrs B9600` to configure a serial port. The `B9600` pattern synonym resolves to `BaudRate 13` (the old glibc kernel-encoding constant baked in at GHC build time), but the runtime glibc 2.42 `cfsetospeed` expects 9600. It interprets 13 as a custom baud rate via `BOTHER`, configuring the port for 13 baud.

### Expected behaviour

`B9600` should set the serial port to 9600 baud. `cfsetospeed` should receive a value that the runtime glibc interprets as 9600 baud.

### Actual behaviour

The port is configured for 13 baud. The device does not respond. Visible via `strace`: `ioctl(TCSETS2, {c_cflag=BOTHER, c_ospeed=13})` instead of `c_cflag=B9600, c_ospeed=9600`. Workaround: use `BaudRate 9600` instead of `B9600`.

### Include debug information

The `BaudRate` pattern synonyms are defined via `hsc2hs` `#const` (e.g. `pattern B9600 = BaudRate (#const B9600)`), capturing glibc's `B9600` macro at GHC build time. In glibc <= 2.41, `B9600 = 13` (kernel encoding). In glibc >= 2.42, `B9600 = 9600` ("sane speed_t"). When GHC is built against old glibc but runs on new glibc, the stale constant 13 is passed to the new versioned `cfsetospeed@GLIBC_2.42`, which treats it as an arbitrary speed.

glibc change: commit [5cf101a85aae](https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=5cf101a85aae0d703cdd8ed7b25fe288e41fdacb) and [relevant changeset](https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=b65e6270fac585b85e18dcd6538ca904d3ed7868). Same bug in Rust: [rust-lang/libc#4692](https://github.com/rust-lang/libc/issues/4692).

### API breaking changes

The `BaudRate` pattern synonyms are now potentially wrong on any system where the build-time and runtime glibc versions straddle the 2.41/2.42 boundary.

### Posix compliance

POSIX specifies `speed_t` as opaque and the `Bxxx` constants as implementation-defined. The issue is that glibc changed their values, but the `unix` package bakes them in at compile time rather than querying them at runtime.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.