From 64cb0cd7d2b65bf30c2ac1a55aeed5b2ece7b992 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Mon, 23 Sep 2024 16:45:25 -0400 Subject: [PATCH 1/4] Mmap: fix grow! for non file IOs --- stdlib/Mmap/src/Mmap.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index e6987582bf511..c517d8755426b 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -86,6 +86,8 @@ grow!(::Anonymous,o::Integer,l::Integer) = return function grow!(io::IO, offset::Integer, len::Integer) pos = position(io) filelen = filesize(io) + # If non-regular file skip trying to grow since we know that will fail the ftruncate syscall + filelen == 0 && !isfile(stat(io)) && return if filelen < offset + len failure = ccall(:jl_ftruncate, Cint, (Cint, Int64), fd(io), offset+len) Base.systemerror(:ftruncate, failure != 0) @@ -218,7 +220,7 @@ function mmap(io::IO, # platform-specific mmapping @static if Sys.isunix() prot, flags, iswrite = settings(file_desc, shared) - if requestedSizeLarger + if isfile(io) && requestedSizeLarger # add a condition to this line to ensure it only checks files if iswrite if grow grow!(io, offset, len) From b5568fe2744e59ee72d4c14023e8d8f2e0db0838 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Mon, 23 Sep 2024 18:48:18 -0400 Subject: [PATCH 2/4] fall back to slower stat filesize if optimized filesize fails (#55641) --- base/iostream.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/iostream.jl b/base/iostream.jl index 762f881cfbecb..74908344e078e 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -230,8 +230,8 @@ end function filesize(s::IOStream) sz = @_lock_ios s ccall(:ios_filesize, Int64, (Ptr{Cvoid},), s.ios) if sz == -1 - err = Libc.errno() - throw(IOError(string("filesize: ", Libc.strerror(err), " for ", s.name), err)) + # if `s` is not seekable `ios_filesize` can fail, so fall back to slower stat method + sz = filesize(stat(s)) end return sz end From a7c648dd99847d494b89c6c296b10f0ec91035d4 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Mon, 23 Sep 2024 20:56:22 -0400 Subject: [PATCH 3/4] define isfile for ::Anonymous --- stdlib/Mmap/src/Mmap.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index c517d8755426b..144eb5fdfcb73 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -45,6 +45,7 @@ Anonymous() = Anonymous("",false,true) Base.isopen(::Anonymous) = true Base.isreadable(::Anonymous) = true Base.iswritable(a::Anonymous) = !a.readonly +Base.isfile(::Anonymous) = true # const used for zeroed, anonymous memory gethandle(io::Anonymous) = INVALID_OS_HANDLE @@ -87,7 +88,7 @@ function grow!(io::IO, offset::Integer, len::Integer) pos = position(io) filelen = filesize(io) # If non-regular file skip trying to grow since we know that will fail the ftruncate syscall - filelen == 0 && !isfile(stat(io)) && return + filelen == 0 && !isfile(io) && return if filelen < offset + len failure = ccall(:jl_ftruncate, Cint, (Cint, Int64), fd(io), offset+len) Base.systemerror(:ftruncate, failure != 0) From 58b31b57457b22bb9ab9f142ffcb96302a164859 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 24 Sep 2024 11:30:02 -0400 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Jameson Nash --- stdlib/Mmap/src/Mmap.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index 144eb5fdfcb73..df2f4f1a19991 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -45,7 +45,6 @@ Anonymous() = Anonymous("",false,true) Base.isopen(::Anonymous) = true Base.isreadable(::Anonymous) = true Base.iswritable(a::Anonymous) = !a.readonly -Base.isfile(::Anonymous) = true # const used for zeroed, anonymous memory gethandle(io::Anonymous) = INVALID_OS_HANDLE @@ -221,7 +220,7 @@ function mmap(io::IO, # platform-specific mmapping @static if Sys.isunix() prot, flags, iswrite = settings(file_desc, shared) - if isfile(io) && requestedSizeLarger # add a condition to this line to ensure it only checks files + if requestedSizeLarger && isfile(io) # add a condition to this line to ensure it only checks files if iswrite if grow grow!(io, offset, len)