Skip to content

Blocking mode of existing fds opened with IO::FileDescriptor.new is changed starting with crystal 1.17 #16507

@digitalshow

Description

@digitalshow

Using https://github.com/xtokio/inotify I noticed that starting with Crystal 1.17 an fd opened with IO::FileDescriptor.new(fd) is set to blocking mode if it is not a pipe/socket/character device.

The fd that was opened non-blocking by inotify_init1(LibC::O_NONBLOCK) is set to blocking mode.

https://github.com/crystal-lang/crystal/pull/15753/files#diff-b84846c2d72cf735f99c4dbc76c81299794b240a7efea623626f344cf62597b3L37-R48

I've got a notion that this one changed behavior on unix: Non-blocking fds that are not a pipe/socket/character device will be set to blocking mode whereas they were left untouched before (because setting value to true did nothing).

Is that an expected change? I couldn't find anything in the changelogs.

For reference some strace logs:

$ crystal --version
Crystal 1.17.1 (2025-07-22)

LLVM: 21.1.2
Default target: x86_64-unknown-linux-gnu
inotify_init1(IN_NONBLOCK)              = 11
...
fcntl(11, F_GETFL)                      = 0x800 (flags O_RDONLY|O_NONBLOCK)
fstat(11, {st_mode=0600, st_size=0, ...}) = 0
fcntl(11, F_GETFL)                      = 0x800 (flags O_RDONLY|O_NONBLOCK)
fcntl(11, F_SETFL, O_RDONLY)            = 0
...
inotify_add_watch(11, "/var/lib/<redacted>", IN_CLOSE_WRITE|IN_DELETE) = 1
...
read(11		<-- blocking
$ crystal --version
Crystal 1.16.3 (2025-05-12)

LLVM: 20.1.8
Default target: x86_64-unknown-linux-gnu
inotify_init1(IN_NONBLOCK)              = 11
...
fcntl(11, F_GETFL)                      = 0x800 (flags O_RDONLY|O_NONBLOCK)
fstat(11, {st_mode=0600, st_size=0, ...}) = 0
...
inotify_add_watch(11, "/var/lib/<redacted>", IN_CLOSE_WRITE|IN_DELETE) = 1
...
read(11, 0x7fb69d9ec000, 40960)         = -1 EAGAIN (Resource temporarily unavailable)

Metadata

Metadata

Assignees

Labels

kind:bugA bug in the code. Does not apply to documentation, specs, etc.kind:regressionSomething that used to correctly work but no longer workstopic:stdlib:runtime

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions