diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index a04f218420e..3c6c7100f5d 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -1610,9 +1610,11 @@ void CurvesGeometry::blend_read(BlendDataReader &reader) CustomData_blend_read(&reader, &this->curve_data, this->curve_num); if (this->curve_offsets) { - BLO_read_int32_array(&reader, this->curve_num + 1, &this->curve_offsets); - this->runtime->curve_offsets_sharing_info = implicit_sharing::info_for_mem_free( - this->curve_offsets); + this->runtime->curve_offsets_sharing_info = BLO_read_shared( + &reader, &this->curve_offsets, [&]() { + BLO_read_int32_array(&reader, this->curve_num + 1, &this->curve_offsets); + return implicit_sharing::info_for_mem_free(this->curve_offsets); + }); } /* Recalculate curve type count cache that isn't saved in files. */ @@ -1631,7 +1633,12 @@ void CurvesGeometry::blend_write(BlendWriter &writer, ID &id) CustomData_blend_write( &writer, &this->curve_data, curve_layers, this->curve_num, CD_MASK_ALL, &id); - BLO_write_int32_array(&writer, this->curve_num + 1, this->curve_offsets); + if (this->curve_offsets) { + BLO_write_shared( + &writer, this->curve_offsets, this->runtime->curve_offsets_sharing_info, [&]() { + BLO_write_int32_array(&writer, this->curve_num + 1, this->curve_offsets); + }); + } } /** \} */ diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 3d1919c57db..ae7b4bc2746 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -5169,48 +5169,52 @@ void CustomData_blend_write(BlendWriter *writer, writer, CustomDataLayer, data->totlayer, data->layers, layers_to_write.data()); for (const CustomDataLayer &layer : layers_to_write) { - switch (layer.type) { - case CD_MDEFORMVERT: - BKE_defvert_blend_write(writer, count, static_cast(layer.data)); - break; - case CD_MDISPS: - write_mdisps( - writer, count, static_cast(layer.data), layer.flag & CD_FLAG_EXTERNAL); - break; - case CD_PAINT_MASK: - BLO_write_raw(writer, sizeof(float) * count, static_cast(layer.data)); - break; - case CD_SCULPT_FACE_SETS: - BLO_write_raw(writer, sizeof(float) * count, static_cast(layer.data)); - break; - case CD_GRID_PAINT_MASK: - write_grid_paint_mask(writer, count, static_cast(layer.data)); - break; - case CD_FACEMAP: - BLO_write_raw(writer, sizeof(int) * count, static_cast(layer.data)); - break; - case CD_PROP_BOOL: - BLO_write_raw(writer, sizeof(bool) * count, static_cast(layer.data)); - break; - case CD_CREASE: - BLO_write_raw(writer, sizeof(float) * count, static_cast(layer.data)); - break; - default: { - const char *structname; - int structnum; - CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum); - if (structnum) { - int datasize = structnum * count; - BLO_write_struct_array_by_name(writer, structname, datasize, layer.data); - } - else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */ - printf("%s error: layer '%s':%d - can't be written to file\n", - __func__, - structname, - layer.type); + BLO_write_shared(writer, layer.data, layer.sharing_info, [&]() { + switch (layer.type) { + case CD_MDEFORMVERT: + BKE_defvert_blend_write(writer, count, static_cast(layer.data)); + break; + case CD_MDISPS: + write_mdisps(writer, + count, + static_cast(layer.data), + layer.flag & CD_FLAG_EXTERNAL); + break; + case CD_PAINT_MASK: + BLO_write_raw(writer, sizeof(float) * count, static_cast(layer.data)); + break; + case CD_SCULPT_FACE_SETS: + BLO_write_raw(writer, sizeof(float) * count, static_cast(layer.data)); + break; + case CD_GRID_PAINT_MASK: + write_grid_paint_mask(writer, count, static_cast(layer.data)); + break; + case CD_FACEMAP: + BLO_write_raw(writer, sizeof(int) * count, static_cast(layer.data)); + break; + case CD_PROP_BOOL: + BLO_write_raw(writer, sizeof(bool) * count, static_cast(layer.data)); + break; + case CD_CREASE: + BLO_write_raw(writer, sizeof(float) * count, static_cast(layer.data)); + break; + default: { + const char *structname; + int structnum; + CustomData_file_write_info(eCustomDataType(layer.type), &structname, &structnum); + if (structnum) { + int datasize = structnum * count; + BLO_write_struct_array_by_name(writer, structname, datasize, layer.data); + } + else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */ + printf("%s error: layer '%s':%d - can't be written to file\n", + __func__, + structname, + layer.type); + } } } - } + }); } if (data->external) { @@ -5286,31 +5290,32 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int layer->sharing_info = nullptr; if (CustomData_verify_versions(data, i)) { - BLO_read_data_address(reader, &layer->data); - if (layer->data != nullptr) { - /* Make layer data shareable. */ - layer->sharing_info = make_implicit_sharing_info_for_layer( - eCustomDataType(layer->type), layer->data, count); - } - if (CustomData_layer_ensure_data_exists(layer, count)) { - /* Under normal operations, this shouldn't happen, but... - * For a CD_PROP_BOOL example, see #84935. - * For a CD_MLOOPUV example, see #90620. */ - CLOG_WARN(&LOG, - "Allocated custom data layer that was not saved correctly for layer->type = %d.", - layer->type); - } + layer->sharing_info = BLO_read_shared(reader, &layer->data, [&]() { + BLO_read_data_address(reader, &layer->data); + if (CustomData_layer_ensure_data_exists(layer, count)) { + /* Under normal operations, this shouldn't happen, but... + * For a CD_PROP_BOOL example, see #84935. + * For a CD_MLOOPUV example, see #90620. */ + CLOG_WARN( + &LOG, + "Allocated custom data layer that was not saved correctly for layer->type = %d.", + layer->type); + } - if (layer->type == CD_MDISPS) { - blend_read_mdisps( - reader, count, static_cast(layer->data), layer->flag & CD_FLAG_EXTERNAL); - } - else if (layer->type == CD_GRID_PAINT_MASK) { - blend_read_paint_mask(reader, count, static_cast(layer->data)); - } - else if (layer->type == CD_MDEFORMVERT) { - BKE_defvert_blend_read(reader, count, static_cast(layer->data)); - } + if (layer->type == CD_MDISPS) { + blend_read_mdisps( + reader, count, static_cast(layer->data), layer->flag & CD_FLAG_EXTERNAL); + } + else if (layer->type == CD_GRID_PAINT_MASK) { + blend_read_paint_mask(reader, count, static_cast(layer->data)); + } + else if (layer->type == CD_MDEFORMVERT) { + BKE_defvert_blend_read(reader, count, static_cast(layer->data)); + } + return layer->data ? make_implicit_sharing_info_for_layer( + eCustomDataType(layer->type), layer->data, count) : + nullptr; + }); i++; } } diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index b4866067015..748a6ae6e75 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -320,6 +320,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address } } + const blender::bke::MeshRuntime *mesh_runtime = mesh->runtime; mesh->runtime = nullptr; BLO_write_id_struct(writer, Mesh, id_address, &mesh->id); @@ -349,7 +350,10 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address writer, &mesh->pdata, poly_layers, mesh->totpoly, CD_MASK_MESH.pmask, &mesh->id); if (mesh->poly_offset_indices) { - BLO_write_int32_array(writer, mesh->totpoly + 1, mesh->poly_offset_indices); + BLO_write_shared( + writer, mesh->poly_offset_indices, mesh_runtime->poly_offsets_sharing_info, [&]() { + BLO_write_int32_array(writer, mesh->totpoly + 1, mesh->poly_offset_indices); + }); } } @@ -395,9 +399,11 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) mesh->runtime = new blender::bke::MeshRuntime(); if (mesh->poly_offset_indices) { - BLO_read_int32_array(reader, mesh->totpoly + 1, &mesh->poly_offset_indices); - mesh->runtime->poly_offsets_sharing_info = blender::implicit_sharing::info_for_mem_free( - mesh->poly_offset_indices); + mesh->runtime->poly_offsets_sharing_info = BLO_read_shared( + reader, &mesh->poly_offset_indices, [&]() { + BLO_read_int32_array(reader, mesh->totpoly + 1, &mesh->poly_offset_indices); + return blender::implicit_sharing::info_for_mem_free(mesh->poly_offset_indices); + }); } /* happens with old files */ diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h index adf53d673e4..821fae8991c 100644 --- a/source/blender/blenloader/BLO_read_write.h +++ b/source/blender/blenloader/BLO_read_write.h @@ -31,6 +31,11 @@ #include "DNA_windowmanager_types.h" /* for eReportType */ +#ifdef __cplusplus +# include "BLI_function_ref.hh" +# include "BLI_implicit_sharing.hh" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -192,6 +197,18 @@ void BLO_write_string(BlendWriter *writer, const char *data_ptr); /* Misc. */ +#ifdef __cplusplus +/** + * Check if the data can be written more efficiently by making use of implicit-sharing. If yes, the + * user count of the sharing-info is increased making the data immutable. The provided callback + * should serialize the potentially shared data. It is only called when necessary. + */ +void BLO_write_shared(BlendWriter *writer, + const void *data, + const blender::ImplicitSharingInfo *sharing_info, + blender::FunctionRef write_fn); +#endif + /** * Sometimes different data is written depending on whether the file is saved to disk or used for * undo. This function returns true when the current file-writing is done for undo. @@ -255,6 +272,35 @@ void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p); /* Misc. */ +#ifdef __cplusplus +} + +void BLO_read_shared_impl(BlendDataReader *reader, + void *data, + const blender::ImplicitSharingInfo **r_sharing_info, + blender::FunctionRef read_fn); + +/** + * Check if there is any shared data for the given data pointer. If yes, return the existing + * sharing-info. If not, call the provided function to actually read the data now. + */ +template +const blender::ImplicitSharingInfo *BLO_read_shared( + BlendDataReader *reader, + T **data_ptr, + blender::FunctionRef read_fn) +{ + const blender::ImplicitSharingInfo *sharing_info; + BLO_read_shared_impl(reader, *data_ptr, &sharing_info, read_fn); + return sharing_info; +} + +# ifdef __cplusplus +extern "C" { +# endif + +#endif + int BLO_read_fileversion_get(BlendDataReader *reader); bool BLO_read_requires_endian_switch(BlendDataReader *reader); bool BLO_read_data_is_undo(BlendDataReader *reader); @@ -287,8 +333,8 @@ struct BlendFileReadReport *BLO_read_lib_reports(BlendLibReader *reader); /* -------------------------------------------------------------------- */ /** \name Blend Expand API * - * BLO_expand has to be called for every data block that should be loaded. If the data block is in - * a separate `.blend` file, it will be pulled from there. + * BLO_expand has to be called for every data block that should be loaded. If the data block is + * in a separate `.blend` file, it will be pulled from there. * \{ */ void BLO_expand_id(BlendExpander *expander, struct ID *id); diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h index 3fba3e2f301..182bc4d2f30 100644 --- a/source/blender/blenloader/BLO_undofile.h +++ b/source/blender/blenloader/BLO_undofile.h @@ -13,6 +13,23 @@ struct GHash; struct Scene; +#ifdef __cplusplus +# include "BLI_implicit_sharing.hh" +# include "BLI_map.hh" + +struct MemFileSharedStorage { + /** + * Maps the data pointer to the sharing info that it is owned by. + */ + blender::Map map; + + ~MemFileSharedStorage(); +}; + +#else +typedef struct MemFileSharedStorage MemFileSharedStorage; +#endif + typedef struct { void *next, *prev; const char *buf; @@ -32,6 +49,11 @@ typedef struct { typedef struct MemFile { ListBase chunks; size_t size; + /** + * Some data is not serialized into a new buffer because the undo-step can take ownership of it + * without making a copy. This is faster and requires less memory. + */ + MemFileSharedStorage *shared_storage; } MemFile; typedef struct MemFileWriteData { @@ -97,12 +119,6 @@ extern void BLO_memfile_clear_future(MemFile *memfile); extern struct Main *BLO_memfile_main_get(struct MemFile *memfile, struct Main *bmain, struct Scene **r_scene); -/** - * Saves .blend using undo buffer. - * - * \return success. - */ -extern bool BLO_memfile_write_file(struct MemFile *memfile, const char *filepath); FileReader *BLO_memfile_new_filereader(MemFile *memfile, int undo_direction); diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index 040efa2c214..6e9494a206e 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -5139,6 +5139,32 @@ void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p) *ptr_p = final_array; } +void BLO_read_shared_impl( + BlendDataReader *reader, + void *data, + const blender::ImplicitSharingInfo **r_sharing_info, + const blender::FunctionRef read_fn) +{ + if (BLO_read_data_is_undo(reader)) { + if (reader->fd->flags & FD_FLAGS_IS_MEMFILE) { + UndoReader *undo_reader = reinterpret_cast(reader->fd->file); + MemFile &memfile = *undo_reader->memfile; + if (memfile.shared_storage) { + /* Check if the data was saved with sharing-info. */ + if (const blender::ImplicitSharingInfo *sharing_info = + memfile.shared_storage->map.lookup_default(data, nullptr)) + { + /* Add a new owner of the data that is passed to the caller. */ + sharing_info->add_user(); + *r_sharing_info = sharing_info; + return; + } + } + } + } + *r_sharing_info = read_fn(); +} + bool BLO_read_data_is_undo(BlendDataReader *reader) { return (reader->fd->flags & FD_FLAGS_IS_MEMFILE); diff --git a/source/blender/blenloader/intern/undofile.cc b/source/blender/blenloader/intern/undofile.cc index ad109117fd5..71685b40b35 100644 --- a/source/blender/blenloader/intern/undofile.cc +++ b/source/blender/blenloader/intern/undofile.cc @@ -48,9 +48,19 @@ void BLO_memfile_free(MemFile *memfile) } MEM_freeN(chunk); } + MEM_delete(memfile->shared_storage); + memfile->shared_storage = nullptr; memfile->size = 0; } +MemFileSharedStorage::~MemFileSharedStorage() +{ + for (const blender::ImplicitSharingInfo *sharing_info : map.values()) { + /* Removing the user makes sure shared data is freed when the undo step was its last owner. */ + sharing_info->remove_user_and_delete_if_last(); + } +} + void BLO_memfile_merge(MemFile *first, MemFile *second) { /* We use this mapping to store the memory buffers from second memfile chunks which are not owned @@ -202,62 +212,6 @@ struct Main *BLO_memfile_main_get(struct MemFile *memfile, return bmain_undo; } -bool BLO_memfile_write_file(struct MemFile *memfile, const char *filepath) -{ - MemFileChunk *chunk; - int file, oflags; - - /* NOTE: This is currently used for autosave and 'quit.blend', - * where _not_ following symlinks is OK, - * however if this is ever executed explicitly by the user, - * we may want to allow writing to symlinks. - */ - - oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC; -#ifdef O_NOFOLLOW - /* use O_NOFOLLOW to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */ - oflags |= O_NOFOLLOW; -#else - /* TODO(sergey): How to deal with symlinks on windows? */ -# ifndef _MSC_VER -# warning "Symbolic links will be followed on undo save, possibly causing CVE-2008-1103" -# endif -#endif - file = BLI_open(filepath, oflags, 0666); - - if (file == -1) { - fprintf(stderr, - "Unable to save '%s': %s\n", - filepath, - errno ? strerror(errno) : "Unknown error opening file"); - return false; - } - - for (chunk = static_cast(memfile->chunks.first); chunk; - chunk = static_cast(chunk->next)) - { -#ifdef _WIN32 - if (size_t(write(file, chunk->buf, uint(chunk->size))) != chunk->size) -#else - if (size_t(write(file, chunk->buf, chunk->size)) != chunk->size) -#endif - { - break; - } - } - - close(file); - - if (chunk) { - fprintf(stderr, - "Unable to save '%s': %s\n", - filepath, - errno ? strerror(errno) : "Unknown error writing file"); - return false; - } - return true; -} - static ssize_t undo_read(FileReader *reader, void *buffer, size_t size) { UndoReader *undo = (UndoReader *)reader; diff --git a/source/blender/blenloader/intern/writefile.cc b/source/blender/blenloader/intern/writefile.cc index 3c74f5faec7..6fe84012dc1 100644 --- a/source/blender/blenloader/intern/writefile.cc +++ b/source/blender/blenloader/intern/writefile.cc @@ -1744,6 +1744,30 @@ void BLO_write_string(BlendWriter *writer, const char *data_ptr) } } +void BLO_write_shared(BlendWriter *writer, + const void *data, + const ImplicitSharingInfoHandle *sharing_info, + const blender::FunctionRef write_fn) +{ + if (data == nullptr) { + return; + } + if (BLO_write_is_undo(writer)) { + if (sharing_info != nullptr) { + MemFile &memfile = *writer->wd->mem.written_memfile; + if (memfile.shared_storage == nullptr) { + memfile.shared_storage = MEM_new(__func__); + } + if (memfile.shared_storage->map.add(data, sharing_info)) { + /* The undo-step takes (shared) ownership of the data, which also makes it immutable. */ + sharing_info->add_user(); + return; + } + } + } + write_fn(); +} + bool BLO_write_is_undo(BlendWriter *writer) { return writer->wd->use_memfile; diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h index 3308391cca4..4526558fd1e 100644 --- a/source/blender/editors/include/ED_undo.h +++ b/source/blender/editors/include/ED_undo.h @@ -111,7 +111,6 @@ void ED_undosys_type_free(void); /* memfile_undo.c */ -struct MemFile *ED_undosys_stack_memfile_get_active(struct UndoStack *ustack); /** * If the last undo step is a memfile one, find the first #MemFileChunk matching given ID * (using its session UUID), and tag it as "changed in the future". diff --git a/source/blender/editors/undo/memfile_undo.cc b/source/blender/editors/undo/memfile_undo.cc index 0df00e5050e..7ceae2945d3 100644 --- a/source/blender/editors/undo/memfile_undo.cc +++ b/source/blender/editors/undo/memfile_undo.cc @@ -348,25 +348,6 @@ void ED_memfile_undosys_type(UndoType *ut) /** \name Utilities * \{ */ -/** - * Ideally we wouldn't need to export global undo internals, - * there are some cases where it's needed though. - */ -static struct MemFile *ed_undosys_step_get_memfile(UndoStep *us_p) -{ - MemFileUndoStep *us = (MemFileUndoStep *)us_p; - return &us->data->memfile; -} - -struct MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack) -{ - UndoStep *us = BKE_undosys_stack_active_with_type(ustack, BKE_UNDOSYS_TYPE_MEMFILE); - if (us) { - return ed_undosys_step_get_memfile(us); - } - return nullptr; -} - void ED_undosys_stack_memfile_id_changed_tag(UndoStack *ustack, ID *id) { UndoStep *us = ustack->step_active; diff --git a/source/blender/windowmanager/intern/wm_files.cc b/source/blender/windowmanager/intern/wm_files.cc index a08918b3c78..e1799f31091 100644 --- a/source/blender/windowmanager/intern/wm_files.cc +++ b/source/blender/windowmanager/intern/wm_files.cc @@ -2028,33 +2028,20 @@ static void wm_autosave_location(char filepath[FILE_MAX]) BLI_path_join(filepath, FILE_MAX, tempdir_base, filename); } -static void wm_autosave_write(Main *bmain, wmWindowManager *wm) +static void wm_autosave_write(Main *bmain) { char filepath[FILE_MAX]; wm_autosave_location(filepath); - /* Fast save of last undo-buffer, now with UI. */ - const bool use_memfile = (U.uiflag & USER_GLOBALUNDO) != 0; - MemFile *memfile = use_memfile ? ED_undosys_stack_memfile_get_active(wm->undo_stack) : nullptr; - if (memfile != nullptr) { - BLO_memfile_write_file(memfile, filepath); - } - else { - if (use_memfile) { - /* This is very unlikely, alert developers of this unexpected case. */ - CLOG_WARN(&LOG, "undo-data not found for writing, fallback to regular file write!"); - } + /* Save as regular blend file with recovery information. */ + const int fileflags = (G.fileflags & ~G_FILE_COMPRESS) | G_FILE_RECOVER_WRITE; - /* Save as regular blend file with recovery information. */ - const int fileflags = (G.fileflags & ~G_FILE_COMPRESS) | G_FILE_RECOVER_WRITE; - - ED_editors_flush_edits(bmain); + ED_editors_flush_edits(bmain); - /* Error reporting into console. */ - BlendFileWriteParams params{}; - BLO_write_file(bmain, filepath, fileflags, ¶ms, nullptr); - } + /* Error reporting into console. */ + BlendFileWriteParams params{}; + BLO_write_file(bmain, filepath, fileflags, ¶ms, nullptr); } static void wm_autosave_timer_begin_ex(wmWindowManager *wm, double timestep) @@ -2088,21 +2075,33 @@ void wm_autosave_timer(Main *bmain, wmWindowManager *wm, wmTimer * /*wt*/) { wm_autosave_timer_end(wm); + /* Time to wait until the next attempt to autosave if it is disabled right now. */ + const double try_again_time_step = 0.01; + /* If a modal operator is running, don't autosave because we might not be in - * a valid state to save. But try again in 10ms. */ + * a valid state to save. */ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) { if (handler_base->type == WM_HANDLER_TYPE_OP) { wmEventHandler_Op *handler = (wmEventHandler_Op *)handler_base; if (handler->op) { - wm_autosave_timer_begin_ex(wm, 0.01); + wm_autosave_timer_begin_ex(wm, try_again_time_step); return; } } } } - wm_autosave_write(bmain, wm); + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + if (object->type == OB_MESH && object->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) { + /* Don't autosave in modes that require #ED_editors_flush_edits to be called because this can + * potentially be very slow. */ + wm_autosave_timer_begin_ex(wm, try_again_time_step); + return; + } + } + + wm_autosave_write(bmain); /* Restart the timer after file write, just in case file write takes a long time. */ wm_autosave_timer_begin(wm); diff --git a/source/blender/windowmanager/intern/wm_init_exit.cc b/source/blender/windowmanager/intern/wm_init_exit.cc index 4cf6e5939c0..b425b4d8c64 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.cc +++ b/source/blender/windowmanager/intern/wm_init_exit.cc @@ -481,27 +481,18 @@ void WM_exit_ex(bContext *C, const bool do_python) /* NOTE: same code copied in `wm_files.cc`. */ if (C && wm) { if (!G.background) { - struct MemFile *undo_memfile = wm->undo_stack ? - ED_undosys_stack_memfile_get_active(wm->undo_stack) : - nullptr; - if (undo_memfile != nullptr) { - /* save the undo state as quit.blend */ - Main *bmain = CTX_data_main(C); - char filepath[FILE_MAX]; - bool has_edited; - const int fileflags = G.fileflags & ~G_FILE_COMPRESS; - - BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE); - - has_edited = ED_editors_flush_edits(bmain); - - BlendFileWriteParams blend_file_write_params{}; - if ((has_edited && - BLO_write_file(bmain, filepath, fileflags, &blend_file_write_params, nullptr)) || - BLO_memfile_write_file(undo_memfile, filepath)) - { - printf("Saved session recovery to \"%s\"\n", filepath); - } + /* Save quit.blend. */ + Main *bmain = CTX_data_main(C); + char filepath[FILE_MAX]; + const int fileflags = G.fileflags & ~G_FILE_COMPRESS; + + BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), BLENDER_QUIT_FILE); + + ED_editors_flush_edits(bmain); + + BlendFileWriteParams blend_file_write_params{}; + if (BLO_write_file(bmain, filepath, fileflags, &blend_file_write_params, nullptr)) { + printf("Saved session recovery to \"%s\"\n", filepath); } } diff --git a/source/creator/creator_signals.c b/source/creator/creator_signals.c index 0912aa12019..121f5ae3c08 100644 --- a/source/creator/creator_signals.c +++ b/source/creator/creator_signals.c @@ -51,12 +51,6 @@ # include "creator_intern.h" /* own include */ -// #define USE_WRITE_CRASH_BLEND -# ifdef USE_WRITE_CRASH_BLEND -# include "BKE_undo_system.h" -# include "BLO_undofile.h" -# endif - /* set breakpoints here when running in debug mode, useful to catch floating point errors */ # if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE) static void sig_handle_fpe(int UNUSED(sig)) @@ -94,28 +88,6 @@ static void sig_handle_crash(int signum) wmWindowManager *wm = G_MAIN ? G_MAIN->wm.first : NULL; -# ifdef USE_WRITE_CRASH_BLEND - if (wm && wm->undo_stack) { - struct MemFile *memfile = BKE_undosys_stack_memfile_get_active(wm->undo_stack); - if (memfile) { - char filepath[FILE_MAX]; - - if (!(G_MAIN && G_MAIN->filepath[0])) { - BLI_path_join(filepath, sizeof(filepath), BKE_tempdir_base(), "crash.blend"); - } - else { - STRNCPY(filepath, G_MAIN->filepath); - BLI_path_extension_replace(filepath, sizeof(filepath), ".crash.blend"); - } - - printf("Writing: %s\n", filepath); - fflush(stdout); - - BLO_memfile_write_file(memfile, filepath); - } - } -# endif - FILE *fp; char header[512];