-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Allow MemoryMappedFile to work on character device #2183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
...braries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs
Show resolved
Hide resolved
...ries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Windows.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments for you to consider.
I made some updates @carlossanlop and this should be ready for another pass. Touching The mmap call will fail on /dev/zero with EACCESS unless fd is opened with So I abandoned the idea that we can open the right stream and pass proper flags for all devices using the file name. If needed, the user can create FileStream as needed and pass more options and we will pass it down to OS for final judgment. I would expect the majority of users to use |
src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm back from vacation. Left a couple of additional comments for you to consider.
...braries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
Outdated
Show resolved
Hide resolved
...braries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
Outdated
Show resolved
Hide resolved
@wfurt, still working on this? |
I updated tests, changed naming and rill-back write-only support as we discussed while back @carlossanlop. This should be ready for another review round. |
...braries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
Show resolved
Hide resolved
...braries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs
Outdated
Show resolved
Hide resolved
I noticed that in MemoryMappedFile.cs, this change removed the code that deletes the file if it didn't use to exist (when the file was created internally via a FileStream). Now if the user calls the I also realized that the newly added behavior difference between Windows and Unix would not be obvious to understand to someone reading this in the future. If you allow me to provide a suggestion, I think that instead of deferring the code, we should create a private method called The Windows version would contain: private void VerifyMemoryMappedFileAccess(MemoryMappedFileAccess access, int capacity, FileStream fileStream, bool existed)
{
if (access == MemoryMappedFileAccess.Read && capacity > fileStream.Length)
{
if (!existed)
{
CleanupFile(fileStream, true, path);
}
throw new ArgumentException(SR.Argument_ReadAccessWithLargeCapacity);
}
} And the Unix methods would contain: private void VerifyMemoryMappedFileAccess(MemoryMappedFileAccess access, int capacity, FileStream fileStream, bool existed, bool out isRegularFile)
{
isRegularFile = true;
Interop.Sys.FileStatus status = default;
if (fileStream != null)
{
int result = Interop.Sys.FStat(fileStream.SafeFileHandle, out status);
if (result != 0)
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
throw Interop.GetExceptionForIoErrno(errorInfo);
}
isRegularFile = (status.Mode & Interop.Sys.FileTypes.S_IFCHR) == 0;
if (isRegularFile)
{
if (access == MemoryMappedFileAccess.Read && capacity > status.Size)
{
if (!existed)
{
CleanupFile(fileStream, true, path);
}
throw new ArgumentException(SR.Argument_ReadAccessWithLargeCapacity);
}
if (access == MemoryMappedFileAccess.Write)
{
throw new ArgumentException(SR.Argument_NewMMFWriteAccessNotAllowed, nameof(access));
}
}
}
} Finally, the new What do you think, @wfurt? cc @jozkee |
It would be good to add a test for that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than Carlos' suggestion, generally looks good.
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
Show resolved
Hide resolved
src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.cs
Show resolved
Hide resolved
I made changes in spirit @carlossanlop suggested and did small updates @stephentoub pointed out. Test seems to be failing for unrelated reasons. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM @wfurt, thanks for making this change. I left one more question in case you want to consider it, but it's not blocking.
I look again and there are three places where CreateCore() is called - two with FileStream and one without. I moved the remaining cage to VerifyMemoryMappedFileAccess() so we can preserve order of the checks. Also the in the case when CreateFromFile is called with string, the CreateCore() is already wrapped in try/catch and it has cleanup so I don't think we need it in the VerifyMemoryMappedFileAccess() function. |
This change will push two argument checks to the platform part and it will not enforce capacity limits on Unix if the file is a special character device.
I don't know if this is sufficient to make GPIO and possibly other HW working but it is now at least possible to map /dev/* entries and read and write.
added test for /dev/zero
fixes https://github.com/dotnet/corefx/issues/30686