-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fs_scandir_next() sometimes returns name but no type #660
Comments
Odd that it works then stops working. According to https://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html:
On what OS and filesystem do you see this happening? |
It's odd indeed, it took me a long time to piece together what was happening here. I access the affected machine remotely, it's managed by our IT department. I'm in contact with them in parallel to figure out if there's something they can do.
I wonder if the network filesystem and its inevitable lag cause any shenanigans somewhere inside libuv … |
Surprised that our docs don't mention this; that should definitely be fixed regardless of whether we return I assume the same applies to |
We can make this return a "unknown" string as well, this is probably the more correct behavior here. I remember reading the code relating this, should be an easy fix, assuming it wasn't intended behavior this shouldn't be a breaking change as well. |
Personally, I think I prefer keeping it as |
I can confirm that function Main()
local luv = require "luv"
local root = "<home>/.local/share/nvim/lazy/vim-snippets/snippets"
local fs = luv.fs_opendir(root, nil, 200)
local data = luv.fs_readdir(fs)
if data then
for _, dirent in ipairs(data) do
print(dirent.type, dirent.name)
end
end
if luv.fs_readdir(fs) then
print("...")
end
luv.fs_closedir(fs)
end
Main() This prints the same (lengthy) output as the original example. Explicitly using function Main()
local luv = require "luv"
local root = "<home>/.local/share/nvim/lazy/vim-snippets/snippets"
local fs = luv.fs_scandir(root)
local name, type = "", ""
while name do
name, type = luv.fs_scandir_next(fs)
if name and not type then
local stat = luv.fs_stat(root .. "/" .. name)
type = stat.type
end
print(type, name)
end
end
Main() |
While libuv/vim.loop docs say that `fs_scandir_next()` either returns `nil` or `string, string` or fails, there is an edge case on networked filesystems. In those cases, `uv__fs_scandir()` returns the type `UV_DIRENT_UNKNOWN` and `luv.fs_scandir_next()` [converts][1] this into returning a single string. This means in those cases, `name` is a string and `type` is `nil`. See [this bug report][2]. The situation can be remedied by explicitly calling `fs_stat()` on those files. This always fetches the correct type, as far as I can see. [1]: https://github.com/luvit/luv/blob/master/src/fs.c#L116 [2]: luvit/luv#660
While libuv/vim.loop docs say that `fs_scandir_next()` either returns `nil` or `string, string` or fails, there is an edge case on networked filesystems. In those cases, `uv__fs_scandir()` returns the type `UV_DIRENT_UNKNOWN` and `luv.fs_scandir_next()` [converts][1] this into returning a single string. This means in those cases, `name` is a string and `type` is `nil`. See [this bug report][2]. The situation can be remedied by explicitly calling `fs_stat()` on those files. This always fetches the correct type, as far as I can see. [1]: https://github.com/luvit/luv/blob/master/src/fs.c#L116 [2]: luvit/luv#660
Hi!
After debugging for a long time why the LuaSnip plugin for Neovim doesn't load all my snippets, I think I've traced the issue to this (otherwise excellent!) library.
The documentation for
luv.fs_scandir_next()
states that the function either returns two strings (file name and directory entry type) ornil
or it fails completely.However, for whatever reason, on the specific machine that I use, I receive the file name as usual but
nil
for the entry type. (MWE at the bottom.) Because downstream Lua scripts expect either two strings or two nils, this breaks a lot of their assumptions and code starts to behave strangely.After some digging, I think I located the issue in fs.c:126: whenever
ent->type
is an unknown enum value, the type is set to the string"unknown"
and two values are returned as usual. However, ifent->type
is the known enum valueUV_DIRENT_UNKNOWN
, then the type is not set at all and only one value is returned.I'm not sure what the correct behavior is here, but I think either the code should be changed (by merging the
UV_DIRENT_UNKNOWN
with the default) or the docs (to inform users that sometimesstring, nil
is returned).Of course, if you can think of a simple reason why the directory entry type suddenly fails to be recognized, I'd be extremely grateful for any pointers. 🙂
No matter how you decide, thanks for your time and hard work!
Minimal example (though I'm not sure how useful it is on most machines):
where mwe.lua:
and the output is:
The text was updated successfully, but these errors were encountered: