Skip to content
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

Fix for reading memory mapped files with DWA compression #1333

Merged

Conversation

darbyjohnston
Copy link
Contributor

Hi, I mentioned this issue at a TSC meeting a couple of months ago, sorry for the delay in creating a PR.

I use a custom class derived from Imf::IStream for reading .exr files that supports memory mapping on Windows and Linux/macOS. I noticed I was getting crashes when reading DWA compressed files, and after looking into it discovered that the DWA code was writing into read only data by casting away the const. I guess for regular I/O this didn't cause an issue since it is buffered, but it does cause a crash with memory mapped data. For example in Visual Studio:

Exception thrown: write access violation.

>	OpenEXR-3_2_d.dll!Imf_3_2::Xdr::read<Imf_3_2::CharPtrIO,char const *>(const char * & in, unsigned __int64 & v) Line 522	C++
 	OpenEXR-3_2_d.dll!Imf_3_2::DwaCompressor::uncompress(const char * inPtr, int inSize, Imath_3_1::Box<Imath_3_1::Vec2<int>> range, const char * & outPtr) Line 2260	C++
 	OpenEXR-3_2_d.dll!Imf_3_2::DwaCompressor::uncompress(const char * inPtr, int inSize, int minY, const char * & outPtr) Line 2218	C++
 	OpenEXR-3_2_d.dll!Imf_3_2::`anonymous namespace'::LineBufferTaskIIF::execute() Line 844	C++
 	IlmThread-3_2_d.dll!IlmThread_3_2::`anonymous namespace'::NullThreadPoolProvider::addTask(IlmThread_3_2::Task * t) Line 372	C++
 	IlmThread-3_2_d.dll!IlmThread_3_2::ThreadPool::addTask(IlmThread_3_2::Task * task) Line 700	C++
 	IlmThread-3_2_d.dll!IlmThread_3_2::ThreadPool::addGlobalTask(IlmThread_3_2::Task * task) Line 723	C++
 	OpenEXR-3_2_d.dll!Imf_3_2::ScanLineInputFile::readPixels(int scanLine1, int scanLine2) Line 1704	C++
 	OpenEXR-3_2_d.dll!Imf_3_2::InputFile::readPixels(int scanLine1, int scanLine2) Line 900	C++
 	OpenEXR-3_2_d.dll!Imf_3_2::InputPart::readPixels(int scanLine1, int scanLine2) Line 65	C++
 	OpenEXR-3_2_d.dll!Imf_3_2::RgbaInputFile::readPixels(int scanLine1, int scanLine2) Line 1356	C++
 	OpenEXRTest.exe!`anonymous namespace'::writeReadScanLines(const char * fileName, int width, int height, Imf_3_2::Compression compression, const Imf_3_2::Array2D<Imf_3_2::Rgba> & p1) Line 353	C++
 	OpenEXRTest.exe!testExistingStreams(const std::string & tempDir) Line 1007	C++
 	OpenEXRTest.exe!main(int argc, char * * argv) Line 245	C++
 	[External Code]	

This PR includes both a fix for the DWA code and adds support for memory mapped I/O to the tests. Specifically:

  • Fix the DWA code by using a small temporary buffer
  • Add memory map support to testExistingStreams
  • Modify testExistingStreams to run the tests with all compression types
  • Move the utility function WidenFilename() to ImfMisc.h/.cpp for use with Windows filenames
  • Change WidenFilename() to use std::wstring_convert()

It would also be nice to change char* IStream::readMemoryMapped() to const char* IStream::readMemoryMapped() since the memory should be read only, or that could be a separate PR.

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
@@ -2250,10 +2251,12 @@ DwaCompressor::uncompress (
// Flip the counters from XDR to NATIVE
//

std::array<uint64_t, NUM_SIZES_SINGLE> counterBuf;
memcpy (counterBuf.data (), inPtr, counterBuf.size() * sizeof (uint64_t));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine since the data is all going to be touched subsequently, this has no performance implication, and may improve things through cache prewarming?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a fairly small buffer, currently NUM_SIZES_SINGLE = 11, so 88 bytes?

Copy link
Contributor

@meshula meshula left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good to me, and having the extra test coverage for memmapped files is great.

@darbyjohnston
Copy link
Contributor Author

Thanks!

It looks like the CI is failing from a network timeout:

Warning: Failed to download action 'https://github.com/gitapi/repos/actions/checkout/tarball/ac593985615ec2ede58e132d2e21d2b1cbd6127c'. Error: The SSL connection could not be established, see inner exception.
Warning: Back off 19.262 seconds before retry.
Warning: Failed to download action 'https://github.com/gitapi/repos/actions/checkout/tarball/ac593985615ec2ede58e132d2e21d2b1cbd6127c'. Error: The SSL connection could not be established, see inner exception.
Warning: Back off 26.111 seconds before retry.
Error: The SSL connection could not be established, see inner exception.

@cary-ilm
Copy link
Member

Thanks for the fix, and especially for the tests! Just to confirm, this should be ABI compatible, right? It looks like you've exposed a previously hidden symbol WidenFilename, but that's the only API/ABI change?

@darbyjohnston
Copy link
Contributor Author

Yes, the only change to the API is exposing the WidenFilename() function. The function only has two lines of code and is sort of Windows specific, so it could also be left out of the public API and just copied to where it is needed.

@cary-ilm
Copy link
Member

It looks like WidenFilename was already duplicated in test/OpenEXRTest/TestUtilFStream.h. Would you mind swapping that out for your version in ImfMisc.h? Better to reduce the duplication

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
@darbyjohnston
Copy link
Contributor Author

Sure thing, I removed the function in test/OpenEXRTest/TestUtilFStream.h and updated the PR.

Copy link
Member

@cary-ilm cary-ilm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@cary-ilm cary-ilm merged commit b37c150 into AcademySoftwareFoundation:main Feb 17, 2023
cary-ilm pushed a commit to cary-ilm/openexr that referenced this pull request Mar 3, 2023
…wareFoundation#1333)

* Test memory mapping

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

* Add Windows memory mapping

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

* Fix for DWAA conpression and memory mapping

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

* Remove duplicate code

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

---------

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
cary-ilm pushed a commit that referenced this pull request Mar 5, 2023
* Test memory mapping

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

* Add Windows memory mapping

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

* Fix for DWAA conpression and memory mapping

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

* Remove duplicate code

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>

---------

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
@cary-ilm cary-ilm added the v3.1.6 label Jul 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants