Skip to content

dd iflag=nonblock doesn't work with stdin (fd 0) #11543

@hyperair

Description

@hyperair

The following invocation (which should slurp all pending characters on the tty and immediately exit) hangs until <enter> is sent:

% rust-dd iflag=nonblock bs=1G count=1 of=/dev/null < /dev/tty
^C

In contrast, gnudd works:

% gnudd iflag=nonblock bs=1G count=1 of=/dev/null < /dev/tty
gnudd: error reading 'standard input': Resource temporarily unavailable
0+0 records in
0+0 records out
0 bytes copied, 8.7214e-05 s, 0.0 kB/s
%

As a workaround, it works with if=/dev/tty:

% dd iflag=nonblock bs=1G count=1 of=/dev/null if=/dev/tty
dd: IO error: Would block
%

The reason this seems to happen is because rust-dd seems to lack the fcntl(0, F_SETFL, O_RDONLY|O_NONBLOCK|O_LARGEFILE) call that gnudd does, as verified with strace:

     0.000075 fcntl(0, F_GETFL)         = 0x8000 (flags O_RDONLY|O_LARGEFILE)
     0.000042 fcntl(0, F_SETFL, O_RDONLY|O_NONBLOCK|O_LARGEFILE) = 0                     <---- this line is present in gnudd but missing in rust-dd
     0.000060 lseek(0, 0, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
     0.000066 mmap(NULL, 1073750016, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7e0d941fe000
     0.000071 read(0, 0x7e0d941ff000, 1073741824) = -1 EAGAIN (Resource temporarily unavailable)
     0.000058 write(2, "gnudd: ", 7gnudd: )    = 7
     0.000046 write(2, "error reading 'standard input'", 30error reading 'standard input') = 30

This was discovered because rust-dd breaks fzf-tab like so: Aloxaf/fzf-tab#549

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions