MightyPirates / OpenComputers

Home of the OpenComputers mod for Minecraft.
https://oc.cil.li
Other
1.59k stars 430 forks source link

Files sometimes can't be opened #2214

Closed malucard closed 7 years ago

malucard commented 7 years ago

I disabled buffering in the settings file so I can edit code externally, and now in my kernel, when loading the libraries, sometimes it will fail when loading the first one (class, required by all of them), but when it succeeds on loading it, the rest will load just fine. By sometimes, I mean like 60% of the time, and it's really driving me nuts. This is my "first" time using OC, so I don't know if the buffering is the cause.

What's interesting is that the error is "class.lua", the name of the file, instead of an error message. Maybe the problem is in my code, and if that's the case, here is the code where it happens:

-- component initialization

function loadfile(path)
  local h, err = fs.open(path)
  if not h then
    error(err) -- happens here: "class.lua"
  end
  local buffer = ""
  repeat
    local data, err = fs.read(h, math.huge)
    if not data and err then
      error(err)
    end
    buffer = buffer .. (data or "")
  until not data
  fs.close(h)
  return load(buffer, "=" .. path)
end

-- dofile definition (doesn't matter, loadfile("class.lua")() also errors)

dofile("class.lua") -- sometimes fails
dofile("Process.lua") -- always succeeds

-- Code that's nothing to do with it
payonel commented 7 years ago

TLDR: fs.open (on a "real" filesystem handler) returns the JUST the filename when it fails to open the file. Not an error message nor the type info of the exception thrown (which in this case is likely FileNotFoundException). The message part of the exception in this case is only the path of the file you tried to open. We aren't probably going to change this error message in this case as many other facilities already expect the filename is the entirety of the message on a failed open. You can check fs.exists first if that helps.

By "[your] kernel" are you saying you are building your own os, and not using openos? This info is helpful to provide when asking questions or making bug reports, including which version of opencomputers you are using.

If you are using openos, I notice you are using fs.open and not io.open

[this part is still openos specific] After the filesystem library resolves the path to the responsible filesystem device handler (the actual backend filesystem handler), it passes the remaining path to said filesystem device. At that point, opening the file and the resultant error message (if any) is out of the control of openos, and it up to the filesystem backend. When an open file fails, the filesystem handlers will only return the filename. Generally this is because either the file does not exist, or in the case of "w" it is read only. In your case, I bet it is because the file doesn't exist (As you are trying to open it for read). Thus, when you error() the message returned from filesystem.open, you are only getting what openos got from the call, which for open is just the filename. Check if fs.exists(path) first, also, as you might be expecting relative path (that is, unless "class.lua" is at /class.lua) I recommend using io.open, in fact, I recommend io.open regardless.

Secondly, I can't speak definitively about the buffering, I would guess it is as you expected.

Thirdly, again if you are using openos (which you might not be) I recommend you use the file handle object rather that invoking read on the filesystem library, it makes for cleaner code, it is a style typical of our system

local file = io.open(path)
-- the object returned by filesystem.open(...) would have the same api and usage pattern
-- but again, I recommend io library
local data = file:read(100)
file:close()
malucard commented 7 years ago

Yes, I meant I'm making an OS; the "fs" is a handle to the filesystem component (got via component.proxy(component.list("filesystem")())). The parts that read the file were (partially) taken from OpenOS's init.lua.

The problem here is that sometimes the file won't open, but sometimes they will, on the exact same code.

I'm using the absolute latest build (I don't remember the exact number), on 1.10.2.

NickNackGus commented 7 years ago

Before spending much more time checking the code - if I understand correctly, some of your files are being edited outside of Minecraft, and run in OpenComputers? You may want to check the OpenComputer config file if you have access. There is an option "bufferChanges". The default setting, true, keeps a copy of the file on your real hard disk in OpenComputers' memory - updating one copy of the file doesn't update the other until the copy in OpenComputers' memory is saved to the real hard disk. Setting the option to false may solve your problem. Be sure to change this when your server (or client if in single player) is not running.

malucard commented 7 years ago

I did disable it, but even then, what you said has nothing to do with the problem. Let me word it better:

Using the exact same code, under the exact same conditions, and trying open the same file, from the game, using a proxy to the filesystem component, it will fail most of the time, but sometimes it will succeed.

Only the first file loaded fails, the rest always succeed, which makes me think you have to wait some time before opening a file stream, but that's yet to be tested.

payonel commented 7 years ago

btw you said dofile("Process.lua") always succeeds, can you give some more info related to that?

malucard commented 7 years ago

Simple; when class.lua doesn't fail and it reaches that part without erroring, it never fails, unlike class.lua.

payonel commented 7 years ago

could be a file lock by your editor on "class.lua", perhaps you are saving and the editor hasn't released an exclusive lock on the file, and the java runtime is unable to open the file for read. Perhaps if you killed your editor process (closed the program) and then tried - does it work every time?

malucard commented 7 years ago

Killed it using xkill, still happens.

Using Atom, if that helps.

payonel commented 7 years ago

cannot reproduce, and we don't officially support editing wold files while the world is running -- though it works for me :/