diff --git a/CMakeLists.txt b/CMakeLists.txt index ac5909db..1e2eea37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,25 +1,16 @@ cmake_minimum_required(VERSION 3.16) -project(HPCore) +project(hpcore) -# Check for gold linker for faster linking time. -execute_process(COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl -ldl,--version OUTPUT_VARIABLE stdout ERROR_QUIET) -if("${stdout}" MATCHES "GNU gold") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") -else() - message(WARNING "GNU gold linker isn't available, using the default system linker.") -endif() +# Force build type to Release build. +set(CMAKE_BUILD_TYPE Release) -add_definitions("-std=c++17 -ldl") #-ldl to support printing stack trace at runtime -set(CMAKE_CXX_FLAGS_DEBUG "-g") # ensure debug symbols are added -set(CMAKE_BUILD_TYPE Debug) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY build) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY build) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build) -# Using buildtype MinSizeRel for smaller build outputs. -#set(CMAKE_BUILD_TYPE "MinSizeRel" FORCE) - -link_directories(/usr/local/lib) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-result") # We have 2 executable build outputs: appbill and hpcore @@ -63,6 +54,8 @@ add_executable(hpcore ) target_link_libraries(hpcore libsodium.a + pthread + libblake3.so libboost_system.a libboost_thread.a libboost_log.a @@ -70,9 +63,7 @@ target_link_libraries(hpcore libboost_filesystem.a libboost_stacktrace_backtrace.a backtrace - pthread ${CMAKE_DL_LIBS} # Needed for stacktrace support - libblake3.so ) add_dependencies(hpcore appbill diff --git a/src/comm/comm_client.cpp b/src/comm/comm_client.cpp index 025946ce..0c8aec04 100644 --- a/src/comm/comm_client.cpp +++ b/src/comm/comm_client.cpp @@ -90,7 +90,7 @@ namespace comm } else { - LOG_ERR << "fork() failed when starting websocat process."; + LOG_ERR << errno << ": fork() failed when starting websocat process."; return -1; } diff --git a/src/comm/comm_server.cpp b/src/comm/comm_server.cpp index af8ecb8b..c8dbe1c8 100644 --- a/src/comm/comm_server.cpp +++ b/src/comm/comm_server.cpp @@ -340,7 +340,7 @@ namespace comm } else { - LOG_ERR << "fork() failed when starting websocketd process."; + LOG_ERR << errno << ": fork() failed when starting websocketd process."; return -1; } diff --git a/src/comm/comm_session.cpp b/src/comm/comm_session.cpp index f21d568e..c1dce3b0 100644 --- a/src/comm/comm_session.cpp +++ b/src/comm/comm_session.cpp @@ -202,12 +202,13 @@ namespace comm { // Prepare the memory segments to map with writev(). iovec memsegs[2]; + uint8_t header_buf[SIZE_HEADER_LEN] = {0, 0, 0, 0, 0, 0, 0, 0}; if (is_binary) { // In binary mode, we need to prefix every message with the message size header. - uint8_t header_buf[SIZE_HEADER_LEN] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t len = message.length(); + // Reserve the first 4 bytes for future (TODO). header_buf[4] = len >> 24; header_buf[5] = (len >> 16) & 0xff; diff --git a/src/main.cpp b/src/main.cpp index b9870a49..1831a375 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -77,7 +77,7 @@ void deinit() hplog::deinit(); } -void signal_handler(int signum) +void sigint_handler(int signum) { LOG_WARN << "Interrupt signal (" << signum << ") received."; deinit(); @@ -85,22 +85,11 @@ void signal_handler(int signum) exit(signum); } -namespace boost +void segfault_handler(int signum) { - - inline void assertion_failed_msg(char const *expr, char const *msg, char const *function, char const * /*file*/, long /*line*/) - { - LOG_ERR << "Expression '" << expr << "' is false in function '" << function << "': " << (msg ? msg : "<...>") << ".\n" - << "Backtrace:\n" - << boost::stacktrace::stacktrace() << '\n'; - std::abort(); - } - - inline void assertion_failed(char const *expr, char const *function, char const *file, long line) - { - ::boost::assertion_failed_msg(expr, 0 /*nullptr*/, function, file, line); - } -} // namespace boost + std::cerr << boost::stacktrace::stacktrace() << "\n"; + exit(SIGABRT); +} /** * Global exception handler for std exceptions. @@ -116,18 +105,16 @@ void std_terminate() noexcept } catch (std::exception &ex) { - LOG_ERR << "std error: " << ex.what() << "\n"; + LOG_ERR << "std error: " << ex.what(); } catch (...) { - LOG_ERR << "std error: Terminated due to unknown exception" - << "\n"; + LOG_ERR << "std error: Terminated due to unknown exception"; } } else { - LOG_ERR << "std error: Terminated due to unknown reason" - << "\n"; + LOG_ERR << "std error: Terminated due to unknown reason"; } LOG_ERR << boost::stacktrace::stacktrace(); @@ -137,6 +124,11 @@ void std_terminate() noexcept int main(int argc, char **argv) { + // Register exception and segfault handlers. + std::set_terminate(&std_terminate); + signal(SIGSEGV, &segfault_handler); + signal(SIGABRT, &segfault_handler); + // seed rand srand(util::get_epoch_milliseconds()); @@ -148,9 +140,6 @@ int main(int argc, char **argv) pthread_sigmask(SIG_BLOCK, &mask, NULL); } - // Register exception handler for std exceptions. - std::set_terminate(&std_terminate); - // Extract the CLI args // This call will populate conf::ctx if (parse_cmd(argc, argv) != 0) @@ -210,7 +199,7 @@ int main(int argc, char **argv) } // After initializing primary subsystems, register the SIGINT handler. - signal(SIGINT, signal_handler); + signal(SIGINT, &sigint_handler); if (cons::run_consensus() == -1) { diff --git a/src/pchheader.hpp b/src/pchheader.hpp index 371de951..bdec2181 100644 --- a/src/pchheader.hpp +++ b/src/pchheader.hpp @@ -3,8 +3,6 @@ // Enable boost strack trace. #define BOOST_STACKTRACE_USE_BACKTRACE -// Enable custom handlers for boost assertion failures. -#define BOOST_ENABLE_ASSERT_DEBUG_HANDLER #include #include diff --git a/src/sc.cpp b/src/sc.cpp index 66b9a819..a8541477 100644 --- a/src/sc.cpp +++ b/src/sc.cpp @@ -13,7 +13,7 @@ namespace sc int execute_contract(execution_context &ctx) { // Start the hpfs rw session before starting the contract process. - if (start_hpfs_rw_session(ctx) != 0) + if (start_hpfs_rw_session(ctx) == -1) return -1; // Setup io pipes and feed all inputs to them. @@ -39,7 +39,7 @@ namespace sc ctx.output_fetcher_thread = std::thread(fetch_outputs, std::ref(ctx)); // Write the inputs into the contract process. - if (feed_inputs(ctx) != 0) + if (feed_inputs(ctx) == -1) { util::kill_process(pid, true); ctx.contract_pid = 0; @@ -102,7 +102,7 @@ namespace sc } else { - LOG_ERR << "fork() failed when starting contract process." << (ctx.args.readonly ? " (rdonly)" : ""); + LOG_ERR << errno << ": fork() failed when starting contract process." << (ctx.args.readonly ? " (rdonly)" : ""); goto failure; } @@ -147,6 +147,7 @@ namespace sc return -1; LOG_DBG << "hpfs session started. pid:" << ctx.hpfs_pid << (ctx.args.readonly ? " (rdonly)" : ""); + return 0; } /** @@ -229,9 +230,9 @@ namespace sc // Establish contract input pipe. int stdinpipe[2]; - if (pipe(stdinpipe) != 0) + if (pipe(stdinpipe) == -1) { - LOG_ERR << "Failed to create pipe to the contract process."; + LOG_ERR << errno << ": Failed to create pipe to the contract process."; return -1; } @@ -243,7 +244,7 @@ namespace sc // Write the json message and close write fd. if (write(stdinpipe[1], json.data(), json.size()) == -1) { - LOG_ERR << "Failed to write to stdin of contract process."; + LOG_ERR << errno << ": Failed to write to stdin of contract process."; return -1; } close(stdinpipe[1]); @@ -254,15 +255,15 @@ namespace sc int feed_inputs(execution_context &ctx) { // Write any input messages to hp->sc pipe. - if (!ctx.args.readonly && write_contract_hp_inputs(ctx) != 0) + if (!ctx.args.readonly && write_contract_hp_inputs(ctx) == -1) return -1; // Write any NPL messages to contract. - if (!ctx.args.readonly && write_npl_messages(ctx) != 0) + if (!ctx.args.readonly && write_npl_messages(ctx) == -1) return -1; // Write any verified (consensus-reached) user inputs to user pipes. - if (write_contract_fdmap_inputs(ctx.userfds, ctx.args.userbufs) != 0) + if (write_contract_fdmap_inputs(ctx.userfds, ctx.args.userbufs) == -1) { LOG_ERR << "Failed to write user inputs to contract."; return -1; @@ -307,7 +308,7 @@ namespace sc */ int write_contract_hp_inputs(execution_context &ctx) { - if (write_iopipe(ctx.hpscfds, ctx.args.hpscbufs.inputs) != 0) + if (write_iopipe(ctx.hpscfds, ctx.args.hpscbufs.inputs) == -1) { LOG_ERR << "Error writing HP inputs to SC"; return -1; @@ -441,7 +442,7 @@ namespace sc for (auto &[pubkey, buflist] : bufmap) { std::vector fds = std::vector(); - if (create_iopipes(fds, !buflist.inputs.empty()) != 0) + if (create_iopipes(fds, !buflist.inputs.empty()) == -1) return -1; fdmap.emplace(pubkey, std::move(fds)); @@ -464,7 +465,7 @@ namespace sc // Loop through input buffers for each pubkey. for (auto &[pubkey, buflist] : bufmap) { - if (write_iopipe(fdmap[pubkey], buflist.inputs) != 0) + if (write_iopipe(fdmap[pubkey], buflist.inputs) == -1) return -1; } @@ -519,11 +520,11 @@ namespace sc int create_iopipes(std::vector &fds, const bool create_inpipe) { int inpipe[2] = {-1, -1}; - if (create_inpipe && pipe(inpipe) != 0) + if (create_inpipe && pipe(inpipe) == -1) return -1; int outpipe[2] = {-1, -1}; - if (pipe(outpipe) != 0) + if (pipe(outpipe) == -1) { if (create_inpipe) { diff --git a/test/bin/hpfs b/test/bin/hpfs index 26d07d5c..763575b7 100755 Binary files a/test/bin/hpfs and b/test/bin/hpfs differ diff --git a/test/vm-cluster/cluster.sh b/test/vm-cluster/cluster.sh index 893c1dbc..e6766fe0 100755 --- a/test/vm-cluster/cluster.sh +++ b/test/vm-cluster/cluster.sh @@ -156,6 +156,7 @@ if [ $mode = "new" ] || [ $mode = "update" ]; then # Copy required files to hpfiles dir. mkdir -p hpfiles/{bin,ssl,nodejs_contract} strip $hpcore/build/hpcore + strip $hpcore/build/appbill cp $hpcore/build/hpcore hpfiles/bin/ cp $hpcore/examples/nodejs_contract/{package.json,echo_contract.js,hp-contract-lib.js} hpfiles/nodejs_contract/ if [ $mode = "new" ]; then @@ -190,9 +191,9 @@ if [ $mode = "reconfig" ]; then # Run hp setup script on the VM and download the generated hp.cfg vmaddr=${vmaddrs[i]} let nodeid=$i+1 - sshpass -p $vmpass ssh $vmuser@$vmaddr '~/hpfiles/setup-hp.sh' - sshpass -p $vmpass scp $vmuser@$vmaddr:~/contract/cfg/hp.cfg ./cfg/node$nodeid.json + { sshpass -p $vmpass ssh $vmuser@$vmaddr '~/hpfiles/setup-hp.sh' && sshpass -p $vmpass scp $vmuser@$vmaddr:~/contract/cfg/hp.cfg ./cfg/node$nodeid.json; } & done + wait fi # Locally update values of download hp.cfg files.