From 4749a7aec4a585c405e43f63a1d5e0084e55b6e3 Mon Sep 17 00:00:00 2001 From: Person Date: Tue, 22 Aug 2017 20:13:25 -0700 Subject: [PATCH] Bug fixes: --Better locks around creating image files in command line programs. --- Source/EmberCommon/JpegUtils.h | 62 ++++++++++++++++++++++++++---- Source/EmberRender/EmberRender.cpp | 11 +++--- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/Source/EmberCommon/JpegUtils.h b/Source/EmberCommon/JpegUtils.h index d8eee29..de6ce50 100644 --- a/Source/EmberCommon/JpegUtils.h +++ b/Source/EmberCommon/JpegUtils.h @@ -3,6 +3,7 @@ #include "EmberCommonPch.h" #define PNG_COMMENT_MAX 8 +static std::recursive_mutex fileCs; /// /// Write a JPEG file. @@ -22,8 +23,20 @@ static bool WriteJpeg(const char* filename, byte* image, size_t width, size_t he { bool b = false; FILE* file; + errno_t fileResult; - if (fopen_s(&file, filename, "wb") == 0) + //Just to be extra safe. + try + { + rlg l(fileCs); + fileResult = fopen_s(&file, filename, "wb"); + } + catch (std::exception) + { + return false; + } + + if (fileResult == 0) { size_t i; jpeg_error_mgr jerr; @@ -126,8 +139,20 @@ static bool WritePng(const char* filename, byte* image, size_t width, size_t hei { bool b = false; FILE* file; + errno_t fileResult; - if (fopen_s(&file, filename, "wb") == 0) + //Just to be extra safe. + try + { + rlg l(fileCs); + fileResult = fopen_s(&file, filename, "wb"); + } + catch (std::exception) + { + return false; + } + + if (fileResult == 0) { png_structp png_ptr; png_infop info_ptr; @@ -261,7 +286,7 @@ static bool SaveBmp(const char* filename, const byte* image, size_t width, size_ BITMAPFILEHEADER bmfh; BITMAPINFOHEADER info; DWORD bwritten; - HANDLE file; + HANDLE file = nullptr; memset (&bmfh, 0, sizeof (BITMAPFILEHEADER)); memset (&info, 0, sizeof (BITMAPINFOHEADER)); bmfh.bfType = 0x4d42; // 0x4d42 = 'BM' @@ -281,7 +306,18 @@ static bool SaveBmp(const char* filename, const byte* image, size_t width, size_ info.biClrUsed = 0; info.biClrImportant = 0; - if ((file = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == NULL) + //Just to be extra safe. + try + { + rlg l(fileCs); + + if ((file = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == NULL) + { + CloseHandle(file); + return false; + } + } + catch (std::exception) { CloseHandle(file); return false; @@ -348,11 +384,21 @@ static bool WriteExr(const char* filename, Rgba* image, size_t width, size_t hei { int iw = int(width); int ih = int(height); - RgbaOutputFile file(filename, iw, ih, WRITE_RGBA); + std::unique_ptr file; + + try + { + rlg l(fileCs); + file = std::make_unique(filename, iw, ih, WRITE_RGBA); + } + catch (std::exception) + { + return false; + } if (enableComments) { - auto& header = const_cast(file.header()); + auto& header = const_cast(file->header()); header.insert("ember_version", StringAttribute(EmberVersion())); header.insert("ember_nickname", StringAttribute(nick)); header.insert("ember_url", StringAttribute(url)); @@ -363,8 +409,8 @@ static bool WriteExr(const char* filename, Rgba* image, size_t width, size_t hei header.insert("ember_genome", StringAttribute(comments.m_Genome)); } - file.setFrameBuffer(image, 1, iw); - file.writePixels(ih); + file->setFrameBuffer(image, 1, iw); + file->writePixels(ih); return true; } catch (std::exception e) diff --git a/Source/EmberRender/EmberRender.cpp b/Source/EmberRender/EmberRender.cpp index e72855c..6dea6a1 100644 --- a/Source/EmberRender/EmberRender.cpp +++ b/Source/EmberRender/EmberRender.cpp @@ -28,7 +28,6 @@ bool EmberRender(EmberOptions& opt) VerbosePrint("Using " << (sizeof(T) == sizeof(float) ? "single" : "double") << " precision."); Timing t; - bool writeSuccess = false; uint padding; size_t i; size_t strips; @@ -304,7 +303,7 @@ bool EmberRender(EmberOptions& opt) { auto filename = MakeSingleFilename(inputPath, opt.Out(), finalEmber.m_Name, opt.Prefix(), opt.Suffix(), "bmp", padding, i, useName); VerbosePrint("Writing " + filename); - writeSuccess = WriteBmp(filename.c_str(), rgb8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH); + auto writeSuccess = WriteBmp(filename.c_str(), rgb8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH); if (!writeSuccess) cout << "Error writing " << filename << "\n"; @@ -317,7 +316,7 @@ bool EmberRender(EmberOptions& opt) { auto filename = MakeSingleFilename(inputPath, opt.Out(), finalEmber.m_Name, opt.Prefix(), opt.Suffix(), "jpg", padding, i, useName); VerbosePrint("Writing " + filename); - writeSuccess = WriteJpeg(filename.c_str(), rgb8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, int(opt.JpegQuality()), opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); + auto writeSuccess = WriteJpeg(filename.c_str(), rgb8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, int(opt.JpegQuality()), opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); if (!writeSuccess) cout << "Error writing " << filename << "\n"; @@ -337,7 +336,7 @@ bool EmberRender(EmberOptions& opt) VerbosePrint("Writing " + filename); vector rgba8Image(size * 4); Rgba32ToRgba8(finalImagep, rgba8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.Transparency()); - writeSuccess = WritePng(filename.c_str(), rgba8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, 1, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); + auto writeSuccess = WritePng(filename.c_str(), rgba8Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, 1, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); if (!writeSuccess) cout << "Error writing " << filename << "\n"; @@ -360,7 +359,7 @@ bool EmberRender(EmberOptions& opt) VerbosePrint("Writing " + filename); vector rgba16Image(size * 4); Rgba32ToRgba16(finalImagep, rgba16Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.Transparency()); - writeSuccess = WritePng(filename.c_str(), (byte*)rgba16Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, 2, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); + auto writeSuccess = WritePng(filename.c_str(), (byte*)rgba16Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, 2, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); if (!writeSuccess) cout << "Error writing " << filename << "\n"; @@ -376,7 +375,7 @@ bool EmberRender(EmberOptions& opt) VerbosePrint("Writing " + filename); vector rgba32Image(size); Rgba32ToRgbaExr(finalImagep, rgba32Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.Transparency()); - writeSuccess = WriteExr(filename.c_str(), rgba32Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); + auto writeSuccess = WriteExr(filename.c_str(), rgba32Image.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.EnableComments(), comments, opt.Id(), opt.Url(), opt.Nick()); if (!writeSuccess) cout << "Error writing " << filename << "\n";