Fix T78758 Alembic export: crash when file is in use by another application

In cases when the output file cannot be opened, an exception is thrown that
was not caught.
This commit is contained in:
Sybren A. Stüvel 2020-08-04 15:23:36 +02:00
parent e1a10b5e53
commit e8483f9bd7
1 changed files with 31 additions and 6 deletions

View File

@ -48,6 +48,7 @@
static CLG_LogRef LOG = {"io.alembic"};
#include <algorithm>
#include <memory>
struct ExportJobData {
Main *bmain;
@ -103,17 +104,41 @@ static void export_startjob(void *customdata,
const bool export_animation = (data->params.frame_start != data->params.frame_end);
// Create the Alembic archive.
ABCArchive abc_archive(data->bmain, scene, data->params, std::string(data->filename));
std::unique_ptr<ABCArchive> abc_archive;
try {
abc_archive = std::make_unique<ABCArchive>(
data->bmain, scene, data->params, std::string(data->filename));
}
catch (const std::exception &ex) {
std::stringstream error_message_stream;
error_message_stream << "Error writing to " << data->filename;
const std::string &error_message = error_message_stream.str();
ABCHierarchyIterator iter(data->depsgraph, &abc_archive, data->params);
// The exception message can be very cryptic (just "iostream error" on Linux, for example), so
// better not to include it in the report.
CLOG_ERROR(&LOG, "%s: %s", error_message.c_str(), ex.what());
WM_report(RPT_ERROR, error_message.c_str());
data->export_ok = false;
return;
}
catch (...) {
// Unknown exception class, so we cannot include its message.
std::stringstream error_message_stream;
error_message_stream << "Unknown error writing to " << data->filename;
WM_report(RPT_ERROR, error_message_stream.str().c_str());
data->export_ok = false;
return;
}
ABCHierarchyIterator iter(data->depsgraph, abc_archive.get(), data->params);
if (export_animation) {
CLOG_INFO(&LOG, 2, "Exporting animation");
// Writing the animated frames is not 100% of the work, but it's our best guess.
const float progress_per_frame = 1.0f / std::max(size_t(1), abc_archive.total_frame_count());
ABCArchive::Frames::const_iterator frame_it = abc_archive.frames_begin();
const ABCArchive::Frames::const_iterator frames_end = abc_archive.frames_end();
const float progress_per_frame = 1.0f / std::max(size_t(1), abc_archive->total_frame_count());
ABCArchive::Frames::const_iterator frame_it = abc_archive->frames_begin();
const ABCArchive::Frames::const_iterator frames_end = abc_archive->frames_end();
for (; frame_it != frames_end; frame_it++) {
double frame = *frame_it;
@ -128,7 +153,7 @@ static void export_startjob(void *customdata,
BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain);
CLOG_INFO(&LOG, 2, "Exporting frame %.2f", frame);
ExportSubset export_subset = abc_archive.export_subset_for_frame(frame);
ExportSubset export_subset = abc_archive->export_subset_for_frame(frame);
iter.set_export_subset(export_subset);
iter.iterate_and_write();