App: prevent recursive abort/commitTransaction

This commit is contained in:
Zheng, Lei
2019-08-21 10:01:21 +08:00
committed by wmayer
parent a6da78b4e5
commit 15b61112b1

View File

@@ -175,6 +175,7 @@ struct DocumentP
int iTransactionMode;
bool rollback;
bool undoing; ///< document in the middle of undo or redo
bool committing;
std::bitset<32> StatusBits;
int iUndoMode;
unsigned int UndoMemSize;
@@ -200,6 +201,7 @@ struct DocumentP
iTransactionMode = 0;
rollback = false;
undoing = false;
committing = false;
StatusBits.set((size_t)Document::Closable, true);
StatusBits.set((size_t)Document::KeepTrailingDigits, true);
StatusBits.set((size_t)Document::Restoring, false);
@@ -1044,8 +1046,9 @@ std::vector<std::string> Document::getAvailableRedoNames() const
}
void Document::openTransaction(const char* name) {
if(isPerformingTransaction()) {
FC_WARN("Cannot open transaction while transacting");
if(isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("Cannot open transaction while transacting");
return;
}
@@ -1054,8 +1057,9 @@ void Document::openTransaction(const char* name) {
int Document::_openTransaction(const char* name, int id)
{
if(isPerformingTransaction()) {
FC_WARN("Cannot open transaction while transacting");
if(isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("Cannot open transaction while transacting");
return 0;
}
@@ -1146,7 +1150,7 @@ void Document::_checkTransaction(DocumentObject* pcDelObj, const Property *What,
void Document::_clearRedos()
{
if(isPerformingTransaction()) {
if(isPerformingTransaction() || d->committing) {
FC_ERR("Cannot clear redo while transacting");
return;
}
@@ -1159,8 +1163,9 @@ void Document::_clearRedos()
}
void Document::commitTransaction() {
if(isPerformingTransaction()) {
FC_WARN("Cannot commit transaction while transacting");
if(isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("Cannot commit transaction while transacting");
return;
}
@@ -1170,11 +1175,13 @@ void Document::commitTransaction() {
void Document::_commitTransaction(bool notify)
{
if(isPerformingTransaction()) {
FC_WARN("Cannot commit transaction while transacting");
if(isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("Cannot commit transaction while transacting");
return;
}
if (d->activeUndoTransaction) {
Base::FlagToggler<> flag(d->committing);
Application::TransactionSignaller signaller(false,true);
int id = d->activeUndoTransaction->getID();
mUndoTransactions.push_back(d->activeUndoTransaction);
@@ -1193,8 +1200,9 @@ void Document::_commitTransaction(bool notify)
}
void Document::abortTransaction() {
if(isPerformingTransaction()) {
FC_WARN("Cannot abort transaction while transacting");
if(isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("Cannot abort transaction while transacting");
return;
}
if (d->activeUndoTransaction)
@@ -1203,18 +1211,17 @@ void Document::abortTransaction() {
void Document::_abortTransaction()
{
if(isPerformingTransaction()) {
FC_WARN("Cannot abort transaction while transacting");
return;
if(isPerformingTransaction() || d->committing) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("Cannot abort transaction while transacting");
}
if (d->activeUndoTransaction) {
if (!d->activeUndoTransaction) {
Base::FlagToggler<bool> flag(d->rollback);
Application::TransactionSignaller signaller(true,true);
{
Base::FlagToggler<bool> flag(d->rollback);
// applying the so far made changes
d->activeUndoTransaction->apply(*this,false);
}
// applying the so far made changes
d->activeUndoTransaction->apply(*this,false);
// destroy the undo
mUndoMap.erase(d->activeUndoTransaction->getID());
@@ -1263,7 +1270,7 @@ bool Document::isTransactionEmpty() const
void Document::clearUndos()
{
if(isPerformingTransaction()) {
if(isPerformingTransaction() || d->committing) {
FC_ERR("Cannot clear undos while transacting");
return;
}
@@ -3034,6 +3041,12 @@ int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool forc
int Document::recompute(const std::vector<App::DocumentObject*> &objs, bool force, bool *hasError, int options)
{
if (d->undoing || d->rollback) {
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("Ignore document recompute on undo/redo");
return 0;
}
int objectCount = 0;
if (testStatus(Document::PartialDoc)) {
if(mustExecute())