diff --git a/src/main/java/dan200/computercraft/core/apis/handles/BinaryReadableHandle.java b/src/main/java/dan200/computercraft/core/apis/handles/BinaryReadableHandle.java index 45f36eaca..77a3b032b 100644 --- a/src/main/java/dan200/computercraft/core/apis/handles/BinaryReadableHandle.java +++ b/src/main/java/dan200/computercraft/core/apis/handles/BinaryReadableHandle.java @@ -212,6 +212,7 @@ else if( count == 0 && m_seekable != null ) } } case 3: // close + checkOpen(); close(); return null; case 4: // seek diff --git a/src/main/java/dan200/computercraft/core/apis/handles/BinaryWritableHandle.java b/src/main/java/dan200/computercraft/core/apis/handles/BinaryWritableHandle.java index 7d78411d3..b280ebdcc 100644 --- a/src/main/java/dan200/computercraft/core/apis/handles/BinaryWritableHandle.java +++ b/src/main/java/dan200/computercraft/core/apis/handles/BinaryWritableHandle.java @@ -95,6 +95,7 @@ else if( args.length > 0 && args[0] instanceof String ) return null; } case 2: // close + checkOpen(); close(); return null; case 3: // seek diff --git a/src/main/java/dan200/computercraft/core/apis/handles/EncodedReadableHandle.java b/src/main/java/dan200/computercraft/core/apis/handles/EncodedReadableHandle.java index 412d29f09..68cdced49 100644 --- a/src/main/java/dan200/computercraft/core/apis/handles/EncodedReadableHandle.java +++ b/src/main/java/dan200/computercraft/core/apis/handles/EncodedReadableHandle.java @@ -152,6 +152,7 @@ else if( count <= BUFFER_SIZE ) return null; } case 3: // close + checkOpen(); close(); return null; default: diff --git a/src/main/java/dan200/computercraft/core/apis/handles/EncodedWritableHandle.java b/src/main/java/dan200/computercraft/core/apis/handles/EncodedWritableHandle.java index a844adaa3..9d81c1b21 100644 --- a/src/main/java/dan200/computercraft/core/apis/handles/EncodedWritableHandle.java +++ b/src/main/java/dan200/computercraft/core/apis/handles/EncodedWritableHandle.java @@ -93,6 +93,7 @@ public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull O return null; } case 3: // close + checkOpen(); close(); return null; default: diff --git a/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java b/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java index 2be67444d..87b40ee2a 100644 --- a/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java +++ b/src/main/java/dan200/computercraft/core/apis/handles/HandleGeneric.java @@ -37,8 +37,13 @@ protected void checkOpen() throws LuaException protected final void close() { m_open = false; - IoUtil.closeQuietly( m_closable ); - m_closable = null; + + Closeable closeable = m_closable; + if( closeable != null ) + { + IoUtil.closeQuietly( closeable ); + m_closable = null; + } } /** diff --git a/src/test/resources/test-rom/spec/apis/fs_spec.lua b/src/test/resources/test-rom/spec/apis/fs_spec.lua index 157e0be88..ad1bfb41c 100644 --- a/src/test/resources/test-rom/spec/apis/fs_spec.lua +++ b/src/test/resources/test-rom/spec/apis/fs_spec.lua @@ -54,6 +54,20 @@ describe("The fs library", function() expect { fs.open("rom/x", "r") }:same { nil, "/rom/x: No such file" } expect { fs.open("x", "r") }:same { nil, "/x: No such file" } end) + + it("errors when closing twice", function() + local handle = fs.open("rom/startup.lua", "r") + handle.close() + expect.error(handle.close):eq("attempt to use a closed file") + end) + end) + + describe("reading in binary mode", function() + it("errors when closing twice", function() + local handle = fs.open("rom/startup.lua", "rb") + handle.close() + expect.error(handle.close):eq("attempt to use a closed file") + end) end) describe("writing", function() @@ -64,6 +78,20 @@ describe("The fs library", function() it("fails on read-only mounts", function() expect { fs.open("rom/x", "w") }:same { nil, "/rom/x: Access denied" } end) + + it("errors when closing twice", function() + local handle = fs.open("test-files/out.txt", "w") + handle.close() + expect.error(handle.close):eq("attempt to use a closed file") + end) + end) + + describe("writing in binary mode", function() + it("errors when closing twice", function() + local handle = fs.open("test-files/out.txt", "wb") + handle.close() + expect.error(handle.close):eq("attempt to use a closed file") + end) end) describe("appending", function()