diff --git a/source/blender/blenlib/BLI_mmap.h b/source/blender/blenlib/BLI_mmap.h index 2a8f507f5c2..4f775b20dd0 100644 --- a/source/blender/blenlib/BLI_mmap.h +++ b/source/blender/blenlib/BLI_mmap.h @@ -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); diff --git a/source/blender/blenlib/intern/BLI_mmap.cc b/source/blender/blenlib/intern/BLI_mmap.cc index 5317e7935ba..e3c1ce9d43e 100644 --- a/source/blender/blenlib/intern/BLI_mmap.cc +++ b/source/blender/blenlib/intern/BLI_mmap.cc @@ -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 diff --git a/source/blender/imbuf/intern/readimage.cc b/source/blender/imbuf/intern/readimage.cc index b58fe7d12ec..ca3f4e13c23 100644 --- a/source/blender/imbuf/intern/readimage.cc +++ b/source/blender/imbuf/intern/readimage.cc @@ -7,6 +7,7 @@ */ #ifdef _WIN32 +# include # include # include # include @@ -167,7 +168,30 @@ ImBuf *IMB_load_image_from_file_descriptor(const int file, const uchar *mem = static_cast(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);