Kakoune: kak reading from file descriptor fails

Created on 12 Sep 2020  路  2Comments  路  Source: mawww/kakoune

Steps

bash $ kak <(echo "hello")
# vs
bash $ vim <(echo "hello")

Outcome

  • kak: blank on /proc/<pid>/fd/<fd-number>
  • vim: shows "hello" on /proc/self/fd/<fd-number> — is ./self a hint?

Expected

kak should be able to read from temporary file descriptors as means to plug it into some bash workflow and analyze some intermediate output easily within my favourite (kak) editor. — especially for reading with familiar syntax highlighting.

  • stdin works: echo "hello" | kak — a valid workaground, not sure if a solution though. It might just be written somewhere editor <(echo "foo"), so compatibility is king.
bug

Most helpful comment

I wasn't familiar with how process substitution worked, so I decided to check it out:

$ python3 -c "import sys; print(sys.argv)" <(echo hello)
['-c', '/dev/fd/63']

On my machine, /dev/fd is a symlink to /proc/self/fd, and /proc/self is a magic symlink that points to the PID of whatever process reads it.

For me, vim <(echo hello) displays /dev/fd/63 on the status line, but the actual buffer name printed by ^G (and displayed in the title bar) is /proc/1175470/fd/63.

For me, kak <(echo hello) produces a buffer named /proc/1176021/fd/63, and 1176021 matches %val{session} so I presume that is the actual correct PID to be reading.

Digging into the source-code, Kakoune calls open_or_create_file_buffer() for every file named on the command-line:

https://github.com/mawww/kakoune/blob/ec3d7c31040afaee65afde15832d9b0ed6b2224d/src/buffer_utils.cc#L95-L108

That reads the file content via a type called MappedFile:

https://github.com/mawww/kakoune/blob/ec3d7c31040afaee65afde15832d9b0ed6b2224d/src/file.cc#L207-L226

That function will silently do nothing if the filesystem entry has zero size, which appears to be the case for pipes:

$ stat -L -c %s <(echo hello)
0

Even if that check were removed, it wouldn't work - Kakoune goes on to read the file with mmap(), which doesn't work for pipes and FIFOs.

Sure enough, if we trick Kakoune into editing the file as a FIFO, it works:

$ pipekak () { kak -e "edit -fifo $1 $1"; }
$ pipekak <(echo hello)

Probably the right thing to do here would be to make open_or_create_buffer() check the file type as well as whether the file exists - if the type is S_IFCHR (character device) or S_IFIFO (guess!) it should call create_fifo_buffer() instead.

All 2 comments

Probably if a file is not seekable, kak should treat it as a fifo buffer, like stdin.

I wasn't familiar with how process substitution worked, so I decided to check it out:

$ python3 -c "import sys; print(sys.argv)" <(echo hello)
['-c', '/dev/fd/63']

On my machine, /dev/fd is a symlink to /proc/self/fd, and /proc/self is a magic symlink that points to the PID of whatever process reads it.

For me, vim <(echo hello) displays /dev/fd/63 on the status line, but the actual buffer name printed by ^G (and displayed in the title bar) is /proc/1175470/fd/63.

For me, kak <(echo hello) produces a buffer named /proc/1176021/fd/63, and 1176021 matches %val{session} so I presume that is the actual correct PID to be reading.

Digging into the source-code, Kakoune calls open_or_create_file_buffer() for every file named on the command-line:

https://github.com/mawww/kakoune/blob/ec3d7c31040afaee65afde15832d9b0ed6b2224d/src/buffer_utils.cc#L95-L108

That reads the file content via a type called MappedFile:

https://github.com/mawww/kakoune/blob/ec3d7c31040afaee65afde15832d9b0ed6b2224d/src/file.cc#L207-L226

That function will silently do nothing if the filesystem entry has zero size, which appears to be the case for pipes:

$ stat -L -c %s <(echo hello)
0

Even if that check were removed, it wouldn't work - Kakoune goes on to read the file with mmap(), which doesn't work for pipes and FIFOs.

Sure enough, if we trick Kakoune into editing the file as a FIFO, it works:

$ pipekak () { kak -e "edit -fifo $1 $1"; }
$ pipekak <(echo hello)

Probably the right thing to do here would be to make open_or_create_buffer() check the file type as well as whether the file exists - if the type is S_IFCHR (character device) or S_IFIFO (guess!) it should call create_fifo_buffer() instead.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dpc picture dpc  路  4Comments

akkartik picture akkartik  路  3Comments

abitofalchemy picture abitofalchemy  路  3Comments

notramo picture notramo  路  3Comments

MasterOfTheTiger picture MasterOfTheTiger  路  4Comments