Skip to content

RandomAccess.Write throws System.IO.IOException: Invalid argument when buffers count is greater than 1024 #108383

@miroslavp

Description

@miroslavp

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)

Metadata

Metadata

Assignees

Labels

area-System.IOin-prThere is an active PR which will close this issue when it is merged

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions