aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2021-06-01 03:25:23 +0300
committerHennadii Stepanov <32963518+hebasto@users.noreply.github.com>2021-06-01 03:27:29 +0300
commit684e687d42f8d20ac349004ec48a3d0924eb0137 (patch)
tree10502b1543620efd78aa1d8a48475307f4a19ead
parentaedf71dcc54f56ba8ba93274add2f40ed26cafd4 (diff)
parent38eb37c0bd29b4cb825de905e8eec87636a5221b (diff)
downloadbitcoin-684e687d42f8d20ac349004ec48a3d0924eb0137.tar.xz
Merge bitcoin-core/gui#123: rpc: Do not accept command while executing another one
38eb37c0bd29b4cb825de905e8eec87636a5221b qt, rpc: Do not accept command while executing another one (Hennadii Stepanov) 0c32b9c5273a4933bda90aa9eb9b7eace6dcaa14 qt, rpc: Accept stop RPC even another command is executing (Hennadii Stepanov) ccf790287c53edbc7b18983e07f520823436c003 qt, rpc, refactor: Return early in RPCConsole::on_lineEdit_returnPressed (Hennadii Stepanov) 5b9c8c9cdd8e12d2e477840df9d6ab809a613c12 qt, rpc: Add "Executing…" message (Hennadii Stepanov) Pull request description: On master (3f512f3d563954547061ee743648b57a900cbe04) it is possible to enter another command while the current command is still being executed. That makes a mess in the output. With this PR: ![Screenshot from 2020-10-29 20-48-55](https://user-images.githubusercontent.com/32963518/97619690-329c0880-1a29-11eb-9f5b-6ae3c02c13b2.png) Some previous context: https://github.com/bitcoin-core/gui/pull/59#issuecomment-715275185 --- It is still possible to enter and execute the `stop` command any time. ACKs for top commit: jarolrod: ACK 38eb37c promag: Tested ACK 38eb37c0bd29b4cb825de905e8eec87636a5221b. Tree-SHA512: 2b37a4b6838bf586b1b5c878192106721f713caeb6252514a6540356aab898986396e0777e73891d331b1be797a4926c20d3f9f38ba2c984ea90d55b0c34f664
-rw-r--r--src/qt/rpcconsole.cpp104
-rw-r--r--src/qt/rpcconsole.h1
-rw-r--r--src/qt/test/apptests.cpp2
3 files changed, 64 insertions, 43 deletions
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 47feb11b29..51bb9da981 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -930,57 +930,71 @@ void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage)
void RPCConsole::on_lineEdit_returnPressed()
{
- QString cmd = ui->lineEdit->text();
+ QString cmd = ui->lineEdit->text().trimmed();
- if(!cmd.isEmpty())
- {
- std::string strFilteredCmd;
- try {
- std::string dummy;
- if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) {
- // Failed to parse command, so we cannot even filter it for the history
- throw std::runtime_error("Invalid command line");
- }
- } catch (const std::exception& e) {
- QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
- return;
+ if (cmd.isEmpty()) {
+ return;
+ }
+
+ std::string strFilteredCmd;
+ try {
+ std::string dummy;
+ if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) {
+ // Failed to parse command, so we cannot even filter it for the history
+ throw std::runtime_error("Invalid command line");
}
+ } catch (const std::exception& e) {
+ QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
+ return;
+ }
+
+ // A special case allows to request shutdown even a long-running command is executed.
+ if (cmd == QLatin1String("stop")) {
+ std::string dummy;
+ RPCExecuteCommandLine(m_node, dummy, cmd.toStdString());
+ return;
+ }
- ui->lineEdit->clear();
+ if (m_is_executing) {
+ return;
+ }
- cmdBeforeBrowsing = QString();
+ ui->lineEdit->clear();
#ifdef ENABLE_WALLET
- WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();
+ WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();
- if (m_last_wallet_model != wallet_model) {
- if (wallet_model) {
- message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));
- } else {
- message(CMD_REQUEST, tr("Executing command without any wallet"));
- }
- m_last_wallet_model = wallet_model;
+ if (m_last_wallet_model != wallet_model) {
+ if (wallet_model) {
+ message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));
+ } else {
+ message(CMD_REQUEST, tr("Executing command without any wallet"));
}
-#endif
-
- message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
- Q_EMIT cmdRequest(cmd, m_last_wallet_model);
-
- cmd = QString::fromStdString(strFilteredCmd);
-
- // Remove command, if already in history
- history.removeOne(cmd);
- // Append command to history
- history.append(cmd);
- // Enforce maximum history size
- while(history.size() > CONSOLE_HISTORY)
- history.removeFirst();
- // Set pointer to end of history
- historyPtr = history.size();
+ m_last_wallet_model = wallet_model;
+ }
+#endif // ENABLE_WALLET
- // Scroll console view to end
- scrollToEnd();
+ message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
+ //: A console message indicating an entered command is currently being executed.
+ message(CMD_REPLY, tr("Executing…"));
+ m_is_executing = true;
+ Q_EMIT cmdRequest(cmd, m_last_wallet_model);
+
+ cmd = QString::fromStdString(strFilteredCmd);
+
+ // Remove command, if already in history
+ history.removeOne(cmd);
+ // Append command to history
+ history.append(cmd);
+ // Enforce maximum history size
+ while (history.size() > CONSOLE_HISTORY) {
+ history.removeFirst();
}
+ // Set pointer to end of history
+ historyPtr = history.size();
+
+ // Scroll console view to end
+ scrollToEnd();
}
void RPCConsole::browseHistory(int offset)
@@ -1010,7 +1024,13 @@ void RPCConsole::startExecutor()
executor->moveToThread(&thread);
// Replies from executor object must go to this object
- connect(executor, &RPCExecutor::reply, this, qOverload<int, const QString&>(&RPCConsole::message));
+ connect(executor, &RPCExecutor::reply, this, [this](int category, const QString& command) {
+ // Remove "Executing…" message.
+ ui->messagesWidget->undo();
+ message(category, command);
+ scrollToEnd();
+ m_is_executing = false;
+ });
// Requests from this object must go to executor
connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 55a1decceb..75f466642b 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -166,6 +166,7 @@ private:
QCompleter *autoCompleter = nullptr;
QThread thread;
WalletModel* m_last_wallet_model{nullptr};
+ bool m_is_executing{false};
/** Update UI with latest network info from model. */
void updateNetworkState();
diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp
index c1d5f84be5..cb3dbd2267 100644
--- a/src/qt/test/apptests.cpp
+++ b/src/qt/test/apptests.cpp
@@ -40,7 +40,7 @@ void TestRpcCommand(RPCConsole* console)
QTest::keyClicks(lineEdit, "getblockchaininfo");
QTest::keyClick(lineEdit, Qt::Key_Return);
QVERIFY(mw_spy.wait(1000));
- QCOMPARE(mw_spy.count(), 2);
+ QCOMPARE(mw_spy.count(), 4);
QString output = messagesWidget->toPlainText();
UniValue value;
value.read(output.right(output.size() - output.lastIndexOf(QChar::ObjectReplacementCharacter) - 1).toStdString());