Added release build support. (#119)

* Cleaned up and updated cmake to have release build support.
* Added segfault handler.
* Added latest hpfs release build.
* Fixed coding issues revealed by release build.
This commit is contained in:
Ravin Perera
2020-09-16 17:51:54 +05:30
committed by GitHub
parent 64efc53cef
commit 93f57efbe3
9 changed files with 44 additions and 63 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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 <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

View File

@@ -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<int> fds = std::vector<int>();
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<int> &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)
{

Binary file not shown.

View File

@@ -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.