Description
Even though this exception sounds very similar to #108322 (comment) , it is actually a very different issue. It occurs in the Unix implementation of the RandomAccess.WriteGatherAtOffset method
This is the stack trace
System.IO.IOException: Invalid argument
at System.IO.RandomAccess.WriteGatherAtOffset(SafeFileHandle handle, IReadOnlyList`1 buffers, Int64 fileOffset)
Looking at the implementation I have noticed that we call Interop.Sys.PWriteV passing the buffersCount as a parameter
|
fixed (Interop.Sys.IOVector* pinnedVectors = &MemoryMarshal.GetReference(vectors)) |
|
{ |
|
bytesWritten = Interop.Sys.PWriteV(handle, pinnedVectors, buffersCount, fileOffset); |
|
} |
which in turn calls the native implementation
|
while ((count = pwritev(fileDescriptor, (struct iovec*)vectors, (int)vectorCount, (off_t)fileOffset)) < 0 && errno == EINTR); |
According to the documentation of pwritev here http://man.he.net/man2/pwritev we cannot pass buffersCount greater than 1024
NOTES
POSIX.1 allows an implementation to place a limit on the number of
items that can be passed in iov. An implementation can advertise its
limit by defining IOV_MAX in <limits.h> or at run time via the return
value from sysconf(_SC_IOV_MAX). On modern Linux systems, the limit is
1024. Back in Linux 2.0 days, this limit was 16.
Reproduction Steps
Call RandomAccess.Write(handle, buffers, fileOffset) by passing list of buffers where buffers are more than 1024
Expected behavior
It should save the buffers to file
Actual behavior
It throws System.IO.IOException: Invalid argument
Regression?
Not tested on .NET6
Known Workarounds
You can split the buffers into smaller lists (<=1024 elements) and call RandomAccess.Write multiple times with the proper offset
Configuration
Which version of .NET is the code running on?
.NET7
What OS and version, and what distro if applicable?
Ubuntu 22.04.3 LTS under WSL2
What is the architecture (x64, x86, ARM, ARM64)?
x64
Do you know whether it is specific to that configuration?
It is specific to the Unix implementation of the RandomAccess.WriteGatherAtOffset method
Other information
Haven't tested it, but this should also affect Read(SafeFileHandle handle, IReadOnlyList<Memory<byte>> buffers, long fileOffset) which calls ReadScatterAtOffset(SafeFileHandle handle, IReadOnlyList<Memory<byte>> buffers, long fileOffset)
Description
Even though this exception sounds very similar to #108322 (comment) , it is actually a very different issue. It occurs in the Unix implementation of the
RandomAccess.WriteGatherAtOffsetmethodThis is the stack trace
Looking at the implementation I have noticed that we call
Interop.Sys.PWriteVpassing thebuffersCountas a parameterruntime/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs
Lines 199 to 202 in 01aa3d9
which in turn calls the native implementation
runtime/src/native/libs/System.Native/pal_io.c
Line 2000 in c049b85
According to the documentation of
pwritevhere http://man.he.net/man2/pwritev we cannot passbuffersCountgreater than 1024Reproduction Steps
Call
RandomAccess.Write(handle, buffers, fileOffset)by passing list of buffers where buffers are more than 1024Expected behavior
It should save the buffers to file
Actual behavior
It throws
System.IO.IOException: Invalid argumentRegression?
Not tested on .NET6
Known Workarounds
You can split the buffers into smaller lists (<=1024 elements) and call
RandomAccess.Writemultiple times with the proper offsetConfiguration
Which version of .NET is the code running on?
.NET7
What OS and version, and what distro if applicable?
Ubuntu 22.04.3 LTS under WSL2
What is the architecture (x64, x86, ARM, ARM64)?
x64
Do you know whether it is specific to that configuration?
It is specific to the Unix implementation of the
RandomAccess.WriteGatherAtOffsetmethodOther information
Haven't tested it, but this should also affect
Read(SafeFileHandle handle, IReadOnlyList<Memory<byte>> buffers, long fileOffset)which callsReadScatterAtOffset(SafeFileHandle handle, IReadOnlyList<Memory<byte>> buffers, long fileOffset)