diff --git a/libraries/custom_appbase/include/eosio/chain/exec_pri_queue.hpp b/libraries/custom_appbase/include/eosio/chain/exec_pri_queue.hpp index 6ef03f4b73..f6d49c45af 100644 --- a/libraries/custom_appbase/include/eosio/chain/exec_pri_queue.hpp +++ b/libraries/custom_appbase/include/eosio/chain/exec_pri_queue.hpp @@ -106,8 +106,10 @@ class exec_pri_queue : public boost::asio::execution_context if (!lhs_que.empty() && (rhs_que.empty() || *rhs_que.top() < *lhs_que.top())) q = lhs; prio_queue& que = priority_que(q); - que.top()->execute(); - que.pop(); + assert(que.top()); + // pop, then execute since read_write queue is used to switch to read window and the pop needs to happen before that lambda starts + auto t = pop(que); + t->execute(); --size; return size > 0; } diff --git a/libraries/custom_appbase/tests/custom_appbase_tests.cpp b/libraries/custom_appbase/tests/custom_appbase_tests.cpp index 3f01740bdd..f62f10b0a5 100644 --- a/libraries/custom_appbase/tests/custom_appbase_tests.cpp +++ b/libraries/custom_appbase/tests/custom_appbase_tests.cpp @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE( default_exec_window ) { app->executor().post( priority::lowest, exec_queue::read_only, [&]() { // read_only_queue should only contain the current lambda function, // and read_write_queue should have executed all its functions - BOOST_REQUIRE_EQUAL( app->executor().read_only_queue_size(), 1u); // pop()s after execute + BOOST_REQUIRE_EQUAL( app->executor().read_only_queue_size(), 0u); // pop()s before execute BOOST_REQUIRE_EQUAL( app->executor().read_exclusive_queue_size(), 0u ); BOOST_REQUIRE_EQUAL( app->executor().read_write_queue_size(), 0u ); app->quit(); @@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE( execute_from_read_only_and_read_write_queues ) { // stop application. Use lowest at the end to make sure this executes the last app->executor().post( priority::lowest, exec_queue::read_only, [&]() { // read_queue should have current function and write_queue's functions are all executed - BOOST_REQUIRE_EQUAL( app->executor().read_only_queue_size(), 1u); // pop()s after execute + BOOST_REQUIRE_EQUAL( app->executor().read_only_queue_size(), 0u); // pop()s before execute BOOST_REQUIRE_EQUAL( app->executor().read_exclusive_queue_size(), 0u); BOOST_REQUIRE_EQUAL( app->executor().read_write_queue_size(), 0u ); app->quit(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b73809254d..d604011bc6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -131,13 +131,13 @@ add_test(NAME nodeos_protocol_feature_test COMMAND tests/nodeos_protocol_feature set_property(TEST nodeos_protocol_feature_test PROPERTY LABELS nonparallelizable_tests) add_test(NAME compute_transaction_test COMMAND tests/compute_transaction_test.py -v -p 2 -n 3 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST compute_transaction_test PROPERTY LABELS nonparallelizable_tests) -add_test(NAME read-only-trx-basic-test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --read-only-threads 1 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_test(NAME read-only-trx-basic-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 1 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST read-only-trx-basic-test PROPERTY LABELS nonparallelizable_tests) -add_test(NAME read-only-trx-parallel-test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --read-only-threads 16 --num-test-runs 3 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_test(NAME read-only-trx-parallel-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 16 --num-test-runs 3 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST read-only-trx-parallel-test PROPERTY LABELS nonparallelizable_tests) -add_test(NAME read-only-trx-parallel-eos-vm-oc-test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --eos-vm-oc-enable all --read-only-threads 16 --num-test-runs 3 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_test(NAME read-only-trx-parallel-eos-vm-oc-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --eos-vm-oc-enable all --read-only-threads 16 --num-test-runs 3 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST read-only-trx-parallel-eos-vm-oc-test PROPERTY LABELS nonparallelizable_tests) -add_test(NAME read-only-trx-parallel-no-oc-test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --eos-vm-oc-enable none --read-only-threads 6 --num-test-runs 2 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_test(NAME read-only-trx-parallel-no-oc-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --eos-vm-oc-enable none --read-only-threads 6 --num-test-runs 2 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST read-only-trx-parallel-no-oc-test PROPERTY LABELS nonparallelizable_tests) add_test(NAME subjective_billing_test COMMAND tests/subjective_billing_test.py -v -p 2 -n 4 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST subjective_billing_test PROPERTY LABELS nonparallelizable_tests) diff --git a/tests/read_only_trx_test.py b/tests/read_only_trx_test.py index 7b6a555bc5..6af91c5a83 100755 --- a/tests/read_only_trx_test.py +++ b/tests/read_only_trx_test.py @@ -6,6 +6,7 @@ import threading import os import platform +import traceback from TestHarness import Account, Cluster, ReturnType, TestHelper, Utils, WalletMgr from TestHarness.TestHelper import AppArgs @@ -102,6 +103,7 @@ def startCluster(): specificExtraNodeosArgs={} # producer nodes will be mapped to 0 through pnodes-1, so the number pnodes is the no-producing API node specificExtraNodeosArgs[pnodes]=" --plugin eosio::net_api_plugin" + specificExtraNodeosArgs[pnodes]+=" --contracts-console " specificExtraNodeosArgs[pnodes]+=" --read-only-write-window-time-us " specificExtraNodeosArgs[pnodes]+=" 10000 " specificExtraNodeosArgs[pnodes]+=" --read-only-read-window-time-us " @@ -228,7 +230,8 @@ def sendReadOnlyTrxOnThread(startId, numTrxs): assert(results[1]['processed']['action_traces'][0]['console'] == "Im a payloadless slow action") assert(int(results[1]['processed']['elapsed']) > 100) except Exception as e: - Print("Exception in sendReadOnlyTrxOnThread: ", e) + Print("Exception in sendReadOnlyTrxOnThread: ", repr(e)) + traceback.print_exc() errorInThread = True # Send regular trxs from mutltiple threads to bump load @@ -242,7 +245,8 @@ def sendTrxsOnThread(startId, numTrxs, opts=None): results = sendTransaction(testAccountName, 'age', {"user": userAccountName, "id": startId + i}, auth=[{"actor": userAccountName, "permission":"active"}], opts=opts) assert(results[0]) except Exception as e: - Print("Exception in sendTrxsOnThread: ", e) + Print("Exception in sendTrxsOnThread: ", repr(e)) + traceback.print_exc() errorInThread = True def doRpc(resource, command, numRuns, fieldIn, expectedValue, code, payload={}): @@ -258,7 +262,8 @@ def doRpc(resource, command, numRuns, fieldIn, expectedValue, code, payload={}): else: assert(ret_json["code"] == code) except Exception as e: - Print("Exception in doRpc: ", e) + Print("Exception in doRpc: ", repr(e)) + traceback.print_exc() errorInThread = True def runReadOnlyTrxAndRpcInParallel(resource, command, fieldIn=None, expectedValue=None, code=None, payload={}):