diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2015-04-28 17:18:32 +0300 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2015-04-28 18:57:56 +0300 |
commit | 85ae4b87afa80527a36d3bd3164a9df6544f0c3b (patch) | |
tree | dc6dbd0992f9bbf97e4fe39f1df038b005e79d00 | |
parent | 7851534541b02a05b8b647be01c726373185f758 (diff) |
Fix T44404: freestyle crashes blender.
The reported crash case seems to be caused by freeing compiled Python
objects in a thread. Now this issue is avoided by allocating a buffer to
store a Python script and using BPY_string_exec() to run the script. This
makes it unnecessary to repeatedly create and destroy Text data blocks.
Many thanks to Campbell Barton for his help on the bug fix.
5 files changed, 65 insertions, 22 deletions
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index add7420b89a..5cd2e16847d 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -927,6 +927,12 @@ void Controller::InsertStyleModule(unsigned index, const char *iFileName) _Canvas->InsertStyleModule(index, sm); } +void Controller::InsertStyleModule(unsigned index, const char *iName, const char *iBuffer) +{ + StyleModule *sm = new BufferedStyleModule(iBuffer, iName, _inter); + _Canvas->InsertStyleModule(index, sm); +} + void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText) { StyleModule *sm = new BlenderStyleModule(iText, iName, _inter); diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h index 9fe57d92cf4..a09964a4e79 100644 --- a/source/blender/freestyle/intern/application/Controller.h +++ b/source/blender/freestyle/intern/application/Controller.h @@ -90,6 +90,7 @@ public: Render *RenderStrokes(Render *re, bool render); void SwapStyleModules(unsigned i1, unsigned i2); void InsertStyleModule(unsigned index, const char *iFileName); + void InsertStyleModule(unsigned index, const char *iName, const char *iBuffer); void InsertStyleModule(unsigned index, const char *iName, struct Text *iText); void AddStyleModule(const char *iFileName); void RemoveStyleModule(unsigned index); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h index 2bc43798878..1d73125f627 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h @@ -36,6 +36,34 @@ struct Text; namespace Freestyle { +class BufferedStyleModule : public StyleModule +{ +public: + BufferedStyleModule(const string& buffer, const string& file_name, Interpreter *inter) : StyleModule(file_name, inter) + { + _buffer = buffer; + } + + virtual ~BufferedStyleModule() + { + } + +protected: + virtual int interpret() + { + PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter); + BLI_assert(py_inter != 0); + return py_inter->interpretString(_buffer, getFileName()); + } + +private: + string _buffer; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BufferedStyleModule") +#endif +}; + class BlenderStyleModule : public StyleModule { public: @@ -62,7 +90,6 @@ private: #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStyleModule") #endif - }; } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 6b102410aa6..8a7753eda92 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -211,16 +211,12 @@ static char *escape_quotes(char *name) return s; } -static Text *create_lineset_handler(Main *bmain, char *layer_name, char *lineset_name) +static char * create_lineset_handler(char *layer_name, char *lineset_name) { + char *fmt = "__import__('parameter_editor').process('%s', '%s')\n"; char *s1 = escape_quotes(layer_name); char *s2 = escape_quotes(lineset_name); - Text *text = BKE_text_add(bmain, lineset_name); - BKE_text_write(text, "import parameter_editor; parameter_editor.process('"); - BKE_text_write(text, s1); - BKE_text_write(text, "', '"); - BKE_text_write(text, s2); - BKE_text_write(text, "')\n"); + char *text = BLI_sprintfN(fmt, s1, s2); MEM_freeN(s1); MEM_freeN(s2); return text; @@ -293,7 +289,7 @@ static bool test_edge_type_conditions(struct edge_type_condition *conditions, return true; } -static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) +static void prepare(Render *re, SceneRenderLayer *srl) { // load mesh re->i.infostr = "Freestyle: Mesh loading"; @@ -369,9 +365,10 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) cout << " " << layer_count+1 << ": " << lineset->name << " - " << (lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl; } - Text *text = create_lineset_handler(bmain, srl->name, lineset->name); - controller->InsertStyleModule(layer_count, lineset->name, text); + char *buffer = create_lineset_handler(srl->name, lineset->name); + controller->InsertStyleModule(layer_count, lineset->name, buffer); controller->toggleLayer(layer_count, true); + MEM_freeN(buffer); if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) { ++use_ridges_and_valleys; ++use_suggestive_contours; @@ -584,9 +581,7 @@ void FRS_init_stroke_rendering(Render *re) Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) { - Main *freestyle_bmain = re->freestyle_bmain; Render *freestyle_render = NULL; - Text *text, *next_text; if (!render) return controller->RenderStrokes(re, false); @@ -607,7 +602,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) // - add style modules // - set parameters // - compute view map - prepare(freestyle_bmain, re, srl); + prepare(re, srl); if (re->test_break(re->tbh)) { controller->CloseFile(); @@ -635,14 +630,6 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) } } - // Free temp main (currently only text blocks are stored there) - for (text = (Text *)freestyle_bmain->text.first; text; text = next_text) { - next_text = (Text *) text->id.next; - - BKE_text_unlink(freestyle_bmain, text); - BKE_libblock_free(freestyle_bmain, text); - } - return freestyle_render; } diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h index 60193590944..ddb79b2df0b 100644 --- a/source/blender/freestyle/intern/system/PythonInterpreter.h +++ b/source/blender/freestyle/intern/system/PythonInterpreter.h @@ -51,6 +51,8 @@ extern "C" { #include "BKE_text.h" #include "BPY_extern.h" + +#include "bpy_util.h" } namespace Freestyle { @@ -105,6 +107,26 @@ public: return 0; } + int interpretString(const string& str, const string& name) + { + ReportList *reports = CTX_wm_reports(_context); + + BKE_reports_clear(reports); + + if (BPY_string_exec(_context, str.c_str()) != 0) { + BPy_errors_to_report(reports); + cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl; + cerr << "Name: " << name << endl; + cerr << "Errors: " << endl; + BKE_reports_print(reports, RPT_ERROR); + return 1; + } + + BKE_reports_clear(reports); + + return 0; + } + int interpretText(struct Text *text, const string& name) { ReportList *reports = CTX_wm_reports(_context); |