crossterm
crossterm copied to clipboard
Regression in 0.24.0 with Docker distroless causing "No such file or directory" error
Describe the bug This took some tracking down!
Using crossterm 0.24 (or 0.25) in Docker with the Google distroless image (gcr.io/distroless/cc) results in a No such file or directory error.
This error does not occur with crossterm 0.23.2. The specific commit which introduced the regression is https://github.com/crossterm-rs/crossterm/commit/f523c110a6c65b5428eeb3f582b2bfe527bfc28f (https://github.com/crossterm-rs/crossterm/pull/680)
Note that this error does not occur when using other base images such as ubuntu, it is specific to the combination of the above distroless image and the changes in the above commit.
To Reproduce Steps to reproduce the behavior:
- Clone the following repo: https://github.com/fdehau/tui-rs
- Create the following
Dockerfile:
FROM rust:1.66.0 as build-env
WORKDIR /app
COPY . /app
RUN cargo build --release --example demo
FROM gcr.io/distroless/cc
COPY --from=build-env /app/target/release/examples/demo /
ENTRYPOINT [ "./demo" ]
- Build the Docker image:
docker build . -t tui:latest --no-cache
- Run the container:
docker run -it tui:latest
- It will fail with the following error (tested on MacOS):
Error: Custom { kind: Other, error: "No such file or directory (os error 2)" }
The issue can be fixed by reverting https://github.com/crossterm-rs/crossterm/commit/f523c110a6c65b5428eeb3f582b2bfe527bfc28f on top of the current master.
OS MacOS
Terminal/Console iterm2
Examining the commit in question the difference appears to be in the handing when the ioctl call reports a zero size:
- in 0.23.2 the logic would return
Ok((0, 0)) - In 0.24.0 the logic will call
tput_size()which ultimately tries to executes thetputcommand which is not available in the distroless container and so results in theNo such file or directoryerror.
I think the fix should be: if the ioctl call reports a zero size then fallback to tput_size() but if that fails then fallback to returning Ok(0, 0). If you agree I'll raise a PR with this simple fix.
cc @Siphalor
But the error is correct, why would we return Ok if it is an error? Perhaps tui should fall back if this function returns an error?
@TimonPost i suppose it depends on whether you wish crossterm to work in environments where tput is not available, such as distroless containers and also alpine.
Ideally it would (and did until 0.24) but if you don’t want to support that then it would be worth making the dependency explicit and updating the error message to make the context of the error clear (it took quite a bit of effort to trace the general No such file or directory back to this specific issue).
This came up also for me in a similar context in https://github.com/mgunyho/tere/issues/93, where my app (still using v0.24) is run in a chroot or clean nix environment as part of an integration test, so the ioctl returns zero size and tput_size() gives the misleading file not found error because tput is not available in those environments.
Note however that #790 removed the zero-size check here, perhaps by mistake? There is also #422, but seems like tput is still used as of 0.27.