Fix #139387: Try to handle mmap exception on Win32

`IMB_load_image_from_file_descriptor` use mmap to read images, and mmap
sometimes can have erroreous state llike accessing a file from network
drives. This patch tries to handle these exceptions like `BLI_mmap_read`
on Win32 (On unix the `sigbus_handler` will be called instead).

Pull Request: https://projects.blender.org/blender/blender/pulls/139472
This commit is contained in:
YimingWu
2025-05-27 10:01:41 +02:00
committed by YimingWu
parent 5d0d54cc81
commit 34cd681a48
3 changed files with 31 additions and 1 deletions

View File

@@ -30,5 +30,6 @@ bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length
void *BLI_mmap_get_pointer(BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT;
size_t BLI_mmap_get_length(const BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT;
bool BLI_mmap_any_io_error(const BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT;
void BLI_mmap_free(BLI_mmap_file *file) ATTR_NONNULL(1);

View File

@@ -219,6 +219,11 @@ size_t BLI_mmap_get_length(const BLI_mmap_file *file)
return file->length;
}
bool BLI_mmap_any_io_error(const BLI_mmap_file *file)
{
return file->io_error;
}
void BLI_mmap_free(BLI_mmap_file *file)
{
#ifndef WIN32

View File

@@ -7,6 +7,7 @@
*/
#ifdef _WIN32
# include <exception>
# include <io.h>
# include <stddef.h>
# include <sys/types.h>
@@ -167,7 +168,30 @@ ImBuf *IMB_load_image_from_file_descriptor(const int file,
const uchar *mem = static_cast<const uchar *>(BLI_mmap_get_pointer(mmap_file));
const size_t size = BLI_mmap_get_length(mmap_file);
ibuf = IMB_load_image_from_memory(mem, size, flags, filepath, filepath, r_colorspace);
/* There could be broken mmap due to network drives and other issues, handles exception the
* same way as in #BLI_mmap_read. Note that if the mmap becomes invalid mid-way through reading,
* external calls in #IMB_load_image_from_memory could leave unfreed memory, but this is the
* limitation of current exception handling method. Ref #139472. */
#ifdef WIN32
__try
{
#endif
ibuf = IMB_load_image_from_memory(mem, size, flags, filepath, filepath, r_colorspace);
#ifdef WIN32
}
__except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH)
{
ibuf = nullptr;
}
#else
/* For unix, if mmap encounters an exception, BLI_mmap_file::io_error would be set. */
if (BLI_mmap_any_io_error(mmap_file)) {
ibuf = nullptr;
}
#endif
imb_mmap_lock();
BLI_mmap_free(mmap_file);