Using the same InitError for startup error in the daemon and the gui makes it possible to run the tests with the gui again:
0BITCOIND=bitcoin-qt ./test/functional/test_runner.py feature_includeconf feature_config_args
Using the same InitError for startup error in the daemon and the gui makes it possible to run the tests with the gui again:
0BITCOIND=bitcoin-qt ./test/functional/test_runner.py feature_includeconf feature_config_args
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
BITCOIND=bitcoin-qt QT_QPA_PLATFORM=minimal
on travis to catch more regressions.
Concept ACK.
Usually, running self-compiled bitcoin-qt
on Linux Mint 19.1 I get a message:
0$ ./src/qt/bitcoin-qt
1qt5ct: using qt5ct plugin
So local run tests on my environment returns errors:
0$ BITCOIND=bitcoin-qt ./test/functional/test_runner.py feature_includeconf feature_config_args
1Temporary test directory at /tmp/test_runner_₿_🏃_20190710_194358
2Traceback (most recent call last):
3 File "/home/hebasto/github/bitcoin/test/functional/create_cache.py", line 28, in <module>
4 CreateCache().main()
5 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_framework.py", line 218, in main
6 self.stop_nodes()
7 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_framework.py", line 397, in stop_nodes
8 node.stop_node(wait=wait)
9 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_node.py", line 276, in stop_node
10 raise AssertionError("Unexpected stderr {} != {}".format(stderr, expected_stderr))
11AssertionError: Unexpected stderr qt5ct: using qt5ct plugin !=
122019-07-10T16:43:58.707000Z TestFramework (INFO): Initializing test directory /tmp/test_runner_₿_🏃_20190710_194358/cache
132019-07-10T16:43:59.616000Z TestFramework (ERROR): Assertion failed
14Traceback (most recent call last):
15 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_framework.py", line 191, in main
16 self.setup_chain()
17 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_framework.py", line 274, in setup_chain
18 self._initialize_chain()
19 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_framework.py", line 514, in _initialize_chain
20 self.stop_nodes()
21 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_framework.py", line 397, in stop_nodes
22 node.stop_node(wait=wait)
23 File "/home/hebasto/github/bitcoin/test/functional/test_framework/test_node.py", line 276, in stop_node
24 raise AssertionError("Unexpected stderr {} != {}".format(stderr, expected_stderr))
25AssertionError: Unexpected stderr qt5ct: using qt5ct plugin !=
262019-07-10T16:43:59.667000Z TestFramework (INFO): Stopping nodes
27[node 0] Cleaning up leftover process
28Traceback (most recent call last):
29 File "./test/functional/test_runner.py", line 661, in <module>
30 main()
31 File "./test/functional/test_runner.py", line 324, in main
32 runs_ci=args.ci,
33 File "./test/functional/test_runner.py", line 356, in run_tests
34 subprocess.check_output([sys.executable, tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir])
35 File "/usr/lib/python3.6/subprocess.py", line 356, in check_output
36 **kwargs).stdout
37 File "/usr/lib/python3.6/subprocess.py", line 438, in run
38 output=stdout, stderr=stderr)
39subprocess.CalledProcessError: Command '['/usr/bin/python3', '/home/hebasto/github/bitcoin/test/functional/create_cache.py', '--cachedir=/home/hebasto/github/bitcoin/test/cache', '--configfile=/home/hebasto/github/bitcoin/test/functional/../config.ini', '--tmpdir=/tmp/test_runner_\u20bf_🏃_20190710_194358/cache']' returned non-zero exit status 1.
147
148 // Daemonize
149 if (daemon(1, 0)) { // don't chdir (1), do close FDs (0)
150- tfm::format(std::cerr, "Error: daemon() failed: %s\n", strerror(errno));
151- return false;
152+ return InitError(strprintf("daemon() failed: %s\n", strerror(errno)));
0 return InitError(strprintf("%s daemon failed: %s\n", PACKAGE_NAME, strerror(errno)));
deamon()
failed, so I’d prefer to keep the (
,)
.
141@@ -146,19 +142,17 @@ static bool AppInit(int argc, char* argv[])
142 #pragma GCC diagnostic push
143 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
144 #endif
145- tfm::format(std::cout, "Bitcoin server starting\n");
146+ tfm::format(std::cout, PACKAGE_NAME "daemon starting\n");
-daemon
mode
-daemon
run time check, so it should be all right, no?
InitError
was supposed to only be called from the AppInit*
functions, to make sure it isn’t called before the appropriate listeners are installed. It seems I lost track of how the initialization process works though.
In bitcoind.cpp
, I only modify the AppInit
function, so the change is obviously correct there.
However, the gui uses a self-brewed AppInit*
, I think. One of the first things in GuiMain
is to // Subscribe to global signals from core
. So it should be fine as well.
I’d presume it would be more difficult to rewrite the Gui init to call the same AppInit
function as bitcoind does, so I’d rather not do that.
458@@ -459,8 +459,11 @@ int GuiMain(int argc, char* argv[])
459 SetupUIArgs();
460 std::string error;
461 if (!node->parseParameters(argc, argv, error)) {
462+ InitError(strprintf("Error parsing command line arguments: %s\n", error));
463+ // Create a message box, because the gui has neither been created nor has subscribed to core signals
464 QMessageBox::critical(nullptr, PACKAGE_NAME,
465- QObject::tr("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
466+ // message can not be translated because translations have not been initialized
std::string
to a QString
, I believe.
458@@ -459,8 +459,11 @@ int GuiMain(int argc, char* argv[])
459 SetupUIArgs();
460 std::string error;
461 if (!node->parseParameters(argc, argv, error)) {
462+ InitError(strprintf("Error parsing command line arguments: %s\n", error));
Just a suggestion, but it would make sense to change InitError()
to node->initError()
here and below, adding a new Node::initError()
method like existing Chain::initError()
and ChainImpl::initError()
methods.
This would prevent error logs being dropped with #10102. Calling InitError
in the bitcoin-gui
process there can’t have any effect because InitError
uses global variables initialized in the bitcoin-node
process. (Ideally the InitError
function wouldn’t even be accessible to gui code, but there is no enforcement yet for GUI code not accessing node globals currently, unlike the enforcement for wallet code not accessing node globals that was added in 78a2fb55c97fbc26f7b74c5b1fb999a2aff8ce88.)
Feel free to ignore this suggestion if it is confusing or too much work, since I can clean this up later.
Excellent suggestion, but I am not sure how to implement this cleanly. We have the ./src/node
and ./src/interface
subdirectories, so it seems I’d have to split the global uiInterface
+InitError
out from ui_interface
into ./src/node/ui
and move the remainder of ui_interface
into ./src/interface/ui
?
I am happy to cherry-pick something if you code this up.
458@@ -459,8 +459,11 @@ int GuiMain(int argc, char* argv[])
459 SetupUIArgs();
460 std::string error;
461 if (!node->parseParameters(argc, argv, error)) {
462+ InitError(strprintf("Error parsing command line arguments: %s\n", error));
463+ // Create a message box, because the gui has neither been created nor has subscribed to core signals
It might be good to note in the comment on line 427 that the handleMessageBox
call there is necessary for these InitError
calls below to work:
It’d also be possible to ensure handlers were properly registered inside InitError
by adding an assert there:
0assert(g_ui_signals.ThreadSafeMessageBox.num_slots() > 0);
How would that add any value? Boost already has this assertion built in:
0terminate called after throwing an instance of 'boost::wrapexcept<boost::signals2::no_slots_error>'
1 what(): boost::signals2::no_slots_error
Oh, I didn’t realize ThreadSafeMessageBox uses last_value<bool>
so an exception will already be thrown. In this case the assert would be redundant.
https://www.boost.org/doc/libs/1_70_0/doc/html/boost/signals2/no_slots_error.html https://www.boost.org/doc/libs/1_70_0/doc/html/boost/signals2/last_value.html https://www.boost.org/doc/libs/1_70_0/doc/html/boost/signals2/last_valu_1_3_37_6_5_1_1_2.html
Also, remove unused <boost/thread.hpp> include (and others)
Avoids GUI code calling a node function, and having to live in the same process
as g_ui_signals and uiInterface global variables.
ACK fa6f402bde146f92ed131e0c9c8e15a55e723307
Tested on Linux Mint 19.1 with system Qt 5.9.5.
The “using qt5ct plugin” message that is printed to stderr
by qt5ct
can be suppressed by the following environment variable:
0QT_LOGGING_RULES="qt5ct.debug=false"
Using this knowledge, feature_includeconf.py
passed:
0$ BITCOIND=bitcoin-qt QT_LOGGING_RULES="qt5ct.debug=false" ./test/functional/test_runner.py feature_includeconf
1Temporary test directory at /tmp/test_runner_₿_🏃_20190713_150236
2Remaining jobs: [feature_includeconf.py]
31/1 - feature_includeconf.py passed, Duration: 10 s
4
5TEST | STATUS | DURATION
6
7feature_includeconf.py | ✓ Passed | 10 s
8
9ALL | ✓ Passed | 10 s (accumulated)
10Runtime: 10 s
And feature_config_args.py
passed too:
0$ BITCOIND=bitcoin-qt QT_LOGGING_RULES="qt5ct.debug=false" ./test/functional/test_runner.py feature_config_args
1Temporary test directory at /tmp/test_runner_₿_🏃_20190713_150609
2Remaining jobs: [feature_config_args.py]
31/1 - feature_config_args.py passed, Duration: 17 s
4
5TEST | STATUS | DURATION
6
7feature_config_args.py | ✓ Passed | 17 s
8
9ALL | ✓ Passed | 17 s (accumulated)
10Runtime: 17 s
@MarcoFalke
Could you add QT_LOGGING_RULES="qt5ct.debug=false"
to the OP?
Could you add QT_LOGGING_RULES=“qt5ct.debug=false” to the OP?
This is specific to your environment. If I add that, I would also have to add XDG_SESSION_TYPE=x11
, because someone might be running on Wayland with Gnome and get the Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome.
)
InitError
function and global variables from GUI code.