Skip to content

Commit

Permalink
Merge pull request #1370 from AntelopeIO/gh-17
Browse files Browse the repository at this point in the history
Make sure all exceptions are caught when executing code in http_plugin's thread pool, so Leap doesn't crash when processing APIs.
  • Loading branch information
greg7mdp authored Jul 28, 2023
2 parents bf12854 + 5d1bb30 commit 2971a61
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 11 deletions.
20 changes: 12 additions & 8 deletions plugins/http_plugin/include/eosio/http_plugin/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,19 @@
_http_plugin.post_http_thread_pool([resp_code=http_resp_code, cb=std::move(cb), \
body=std::move(body), \
http_fwd = std::move(http_fwd)]() { \
chain::t_or_exception<call_result> result = http_fwd(); \
if (std::holds_alternative<fc::exception_ptr>(result)) { \
try { \
std::get<fc::exception_ptr>(result)->dynamic_rethrow_exception(); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
try { \
chain::t_or_exception<call_result> result = http_fwd(); \
if (std::holds_alternative<fc::exception_ptr>(result)) { \
try { \
std::get<fc::exception_ptr>(result)->dynamic_rethrow_exception(); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
} else { \
cb(resp_code, fc::variant(std::get<call_result>(std::move(result)))); \
} \
} else { \
cb(resp_code, fc::variant(std::get<call_result>(std::move(result)))); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
}); \
} catch (...) { \
Expand Down
3 changes: 0 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,6 @@ add_test(NAME full-version-label-test COMMAND tests/full-version-label.sh "v${VE
add_test(NAME nested_container_multi_index_test COMMAND tests/nested_container_multi_index_test.py -n 2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nested_container_multi_index_test PROPERTY LABELS nonparallelizable_tests)

add_test(NAME nodeos_run_check_test COMMAND tests/nodeos_run_test.py -v ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_run_check_test PROPERTY LABELS nonparallelizable_tests)

add_test(NAME p2p_multiple_listen_test COMMAND tests/p2p_multiple_listen_test.py -v ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST p2p_multiple_listen_test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME p2p_no_listen_test COMMAND tests/p2p_no_listen_test.py -v ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
Expand Down
29 changes: 29 additions & 0 deletions tests/nodeos_run_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,35 @@
accounts=[testeraAccount, currencyAccount, exchangeAccount]
cluster.validateAccounts(accounts)

# run a get_table_rows API call for a table which has an incorrect abi (missing type), to make sure that
# the resulting exception in http-plugin is caught and doesn't cause nodeos to crash (leap issue #1372).
contractDir="unittests/contracts/eosio.token"
wasmFile="eosio.token.wasm"
abiFile="eosio.token.bad.abi"
Print("Publish contract")
trans=node.publishContract(currencyAccount, contractDir, wasmFile, abiFile, waitForTransBlock=True)
if trans is None:
cmdError("%s set contract currency1111" % (ClientName))
errorExit("Failed to publish contract.")

contract="currency1111"
table="accounts"
row0=node.getTableRow(contract, currencyAccount.name, table, 0)

# because we set a bad abi (missing type, see "eosio.token.bad.abi") on the contract, the
# getTableRow() is expected to fail and return None
try:
assert(not row0)
except (AssertionError, KeyError) as _:
Print("ERROR: Failed get table row assertion. %s" % (row0))
raise

# However check that the node is still running and didn't crash when processing getTableRow on a contract
# with a bad abi. If node does crash and we get an exception during "get info", it means that we did not
# catch the exception that occured while calling `cb()` in `http_plugin/macros.hpp`.
currentBlockNum=node.getHeadBlockNum()
Print("CurrentBlockNum: %d" % (currentBlockNum))

testSuccessful=True
finally:
TestHelper.shutdown(cluster, walletMgr, testSuccessful, dumpErrorDetails)
Expand Down
2 changes: 2 additions & 0 deletions unittests/contracts/eosio.token/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ else()
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/eosio.token.wasm ${CMAKE_CURRENT_BINARY_DIR}/eosio.token.wasm COPYONLY )
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/eosio.token.abi ${CMAKE_CURRENT_BINARY_DIR}/eosio.token.abi COPYONLY )
endif()
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/eosio.token.bad.abi ${CMAKE_CURRENT_BINARY_DIR}/eosio.token.bad.abi COPYONLY )

193 changes: 193 additions & 0 deletions unittests/contracts/eosio.token/eosio.token.bad.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
{
"____comment": "This file was generated with eosio-abigen. Manually edited to add a table named global with an undefined type ",
"version": "eosio::abi/1.2",
"types": [],
"structs": [
{
"name": "account",
"base": "",
"fields": [
{
"name": "balance",
"type": "asset"
}
]
},
{
"name": "close",
"base": "",
"fields": [
{
"name": "owner",
"type": "name"
},
{
"name": "symbol",
"type": "symbol"
}
]
},
{
"name": "create",
"base": "",
"fields": [
{
"name": "issuer",
"type": "name"
},
{
"name": "maximum_supply",
"type": "asset"
}
]
},
{
"name": "currency_stats",
"base": "",
"fields": [
{
"name": "supply",
"type": "asset"
},
{
"name": "max_supply",
"type": "asset"
},
{
"name": "issuer",
"type": "name"
}
]
},
{
"name": "issue",
"base": "",
"fields": [
{
"name": "to",
"type": "name"
},
{
"name": "quantity",
"type": "asset"
},
{
"name": "memo",
"type": "string"
}
]
},
{
"name": "open",
"base": "",
"fields": [
{
"name": "owner",
"type": "name"
},
{
"name": "symbol",
"type": "symbol"
},
{
"name": "ram_payer",
"type": "name"
}
]
},
{
"name": "retire",
"base": "",
"fields": [
{
"name": "quantity",
"type": "asset"
},
{
"name": "memo",
"type": "string"
}
]
},
{
"name": "transfer",
"base": "",
"fields": [
{
"name": "from",
"type": "name"
},
{
"name": "to",
"type": "name"
},
{
"name": "quantity",
"type": "asset"
},
{
"name": "memo",
"type": "string"
}
]
}
],
"actions": [
{
"name": "close",
"type": "close",
"ricardian_contract": ""
},
{
"name": "create",
"type": "create",
"ricardian_contract": ""
},
{
"name": "issue",
"type": "issue",
"ricardian_contract": ""
},
{
"name": "open",
"type": "open",
"ricardian_contract": ""
},
{
"name": "retire",
"type": "retire",
"ricardian_contract": ""
},
{
"name": "transfer",
"type": "transfer",
"ricardian_contract": ""
}
],
"tables": [
{
"name": "accounts",
"type": "account",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "stat",
"type": "currency_stats",
"index_type": "i64",
"key_names": [],
"key_types": []
},
{
"name": "global",
"type": "global",
"index_type": "i64",
"key_names": [],
"key_types": []
}
],
"ricardian_clauses": [],
"variants": [],
"action_results": []
}

0 comments on commit 2971a61

Please sign in to comment.