BKE_reports: make the API thread-safe.
This commit makes using (most of) `BKE_report` API safe in
multi-threaded situation.
This is achieved by adding a `std::mutex` lock to the `ReportList`
struct (in a slightly convoluted way unfortunately, due to this being a
DNA struct). This lock is then used to make most operations on
`Reportlist` data thread-safe.
Note that while working on this, a few other minor issues aroze in
existing usages of Reportlist by the WM code, mainly the fact that
`wm_init_reports` and `wm_free_reports` were both useless:
- init was called in a context where there is not yet any WM, so it
was doing nothing.
- free was called on a WM that would be later freed (as part of Main
freeing), which would also call cleanup code for its `reports` data.
Both have been removed.
Further more, `wm_add_default` (which is the only place where a WM ID is
created) did not initialize properly it reports data, this has been
fixed.
This change is related to the wmJob thread-safety tasks and PRs (#112537,
!113548).
Pull Request: https://projects.blender.org/blender/blender/pulls/113561
This commit is contained in:
committed by
Bastien Montagne
parent
db2328436e
commit
9859622a66
@@ -33,7 +33,7 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool
|
||||
report_str = BKE_reports_string(reports, RPT_ERROR);
|
||||
|
||||
if (clear == true) {
|
||||
BKE_reports_clear(reports);
|
||||
BKE_reports_free(reports);
|
||||
}
|
||||
|
||||
if (report_str) {
|
||||
|
||||
@@ -18,7 +18,10 @@ extern "C" {
|
||||
|
||||
struct ReportList;
|
||||
|
||||
/* error reporting */
|
||||
/** Error reporting: convert BKE_report (#ReportList) reports into python errors.
|
||||
*
|
||||
* \param clear: When `true`, #BKE_reports_free is called on the given `reports`, which should
|
||||
* then be considered as 'freed' data and not used anymore. */
|
||||
short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, bool clear);
|
||||
/**
|
||||
* A version of #BKE_report_write_file_fp that uses Python's stdout.
|
||||
|
||||
@@ -281,11 +281,9 @@ static bool bpy_run_string_impl(bContext *C,
|
||||
|
||||
ReportList *wm_reports = CTX_wm_reports(C);
|
||||
if (wm_reports) {
|
||||
BLI_movelisttolist(&wm_reports->list, &reports.list);
|
||||
}
|
||||
else {
|
||||
BKE_reports_clear(&reports);
|
||||
BKE_reports_move_to_reports(wm_reports, &reports);
|
||||
}
|
||||
BKE_reports_free(&reports);
|
||||
}
|
||||
else {
|
||||
Py_DECREF(retval);
|
||||
|
||||
@@ -575,6 +575,8 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject * /*args*/)
|
||||
BKE_blendfile_link_append_context_free(lapp_context);
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
|
||||
|
||||
BKE_reports_free(&self->reports);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,17 +187,18 @@ static PyObject *bpy_lib_write(BPy_PropertyRNA *self, PyObject *args, PyObject *
|
||||
|
||||
if (retval) {
|
||||
BKE_reports_print(&reports, RPT_ERROR_ALL);
|
||||
BKE_reports_clear(&reports);
|
||||
ret = Py_None;
|
||||
Py_INCREF(ret);
|
||||
}
|
||||
else {
|
||||
if (BPy_reports_to_error(&reports, PyExc_IOError, true) == 0) {
|
||||
if (BPy_reports_to_error(&reports, PyExc_IOError, false) == 0) {
|
||||
PyErr_SetString(PyExc_IOError, "Unknown error writing library data");
|
||||
}
|
||||
ret = nullptr;
|
||||
}
|
||||
|
||||
BKE_reports_free(&reports);
|
||||
|
||||
finally:
|
||||
|
||||
/* clear all flags for ID's added to the store (may run on error too) */
|
||||
|
||||
@@ -263,6 +263,7 @@ static PyObject *pyop_call(PyObject * /*self*/, PyObject *args)
|
||||
|
||||
BKE_reports_clear(reports);
|
||||
if ((reports->flag & RPT_FREE) == 0) {
|
||||
BKE_reports_free(reports);
|
||||
MEM_freeN(reports);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -8792,7 +8792,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
|
||||
BKE_reports_init(&reports_temp, reports->flag | RPT_PRINT_HANDLED_BY_OWNER);
|
||||
reports_temp.storelevel = reports->storelevel;
|
||||
BPy_errors_to_report(&reports_temp);
|
||||
BLI_movelisttolist(&reports->list, &reports_temp.list);
|
||||
BKE_reports_move_to_reports(reports, &reports_temp);
|
||||
BKE_reports_free(&reports_temp);
|
||||
}
|
||||
|
||||
/* Also print in the console for Python. */
|
||||
@@ -9006,11 +9007,12 @@ static PyObject *pyrna_register_class(PyObject * /*self*/, PyObject *py_class)
|
||||
if (!has_error) {
|
||||
BPy_reports_write_stdout(&reports, error_prefix);
|
||||
}
|
||||
BKE_reports_clear(&reports);
|
||||
if (has_error) {
|
||||
BKE_reports_free(&reports);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
BKE_reports_free(&reports);
|
||||
|
||||
/* Python errors validating are not converted into reports so the check above will fail.
|
||||
* the cause for returning nullptr will be printed as an error */
|
||||
|
||||
Reference in New Issue
Block a user