aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_core/tx_pool.cpp2
-rw-r--r--src/daemonizer/posix_fork.cpp91
-rw-r--r--src/multisig/multisig_tx_builder_ringct.cpp4
-rw-r--r--src/net/i2p_address.cpp12
-rw-r--r--src/net/tor_address.cpp14
-rw-r--r--src/p2p/net_node.h1
-rw-r--r--src/p2p/net_node.inl48
-rw-r--r--src/wallet/wallet2.cpp1
8 files changed, 124 insertions, 49 deletions
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index badcde361..aec0b64f4 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -416,7 +416,7 @@ namespace cryptonote
break;
try
{
- const crypto::hash &txid = it->second;
+ const crypto::hash txid = it->second;
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
{
diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp
index 16758215d..39e9f7b5f 100644
--- a/src/daemonizer/posix_fork.cpp
+++ b/src/daemonizer/posix_fork.cpp
@@ -5,13 +5,19 @@
//
#include "daemonizer/posix_fork.h"
+#include "misc_language.h"
#include "misc_log_ex.h"
+#include <cerrno>
#include <cstdlib>
+#include <cstring>
#include <fcntl.h>
+#include <fstream>
#include <unistd.h>
#include <stdexcept>
#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
#ifndef TMPDIR
#define TMPDIR "/tmp"
@@ -35,26 +41,64 @@ void fork(const std::string & pidfile)
// processes.
// Only in the final child process do we write the PID to the
// file (and close it).
- std::ofstream pidofs;
+ int pid_fd = -1;
+ auto close_pid_fd = [&pid_fd]()
+ {
+ if (pid_fd >= 0)
+ {
+ close(pid_fd);
+ pid_fd = -1;
+ }
+ };
+ epee::misc_utils::auto_scope_leave_caller pid_fd_guard =
+ epee::misc_utils::create_scope_leave_handler(close_pid_fd);
if (! pidfile.empty ())
{
- int oldpid;
- std::ifstream pidrifs;
- pidrifs.open(pidfile, std::fstream::in);
- if (! pidrifs.fail())
+ struct stat st;
+ if (lstat(pidfile.c_str(), &st) == 0)
{
- // Read the PID and send signal 0 to see if the process exists.
- if (pidrifs >> oldpid && oldpid > 1 && kill(oldpid, 0) == 0)
+ if (S_ISLNK(st.st_mode))
{
- quit("PID file " + pidfile + " already exists and the PID therein is valid");
- }
- pidrifs.close();
- }
+ quit("PID file path is a symlink, refusing: " + pidfile);
+ }
+ if (!S_ISREG(st.st_mode))
+ {
+ quit("PID file path exists and is not a regular file: " + pidfile);
+ }
- pidofs.open(pidfile, std::fstream::out | std::fstream::trunc);
- if (pidofs.fail())
+ int oldpid = 0;
+ std::ifstream pidrifs;
+ pidrifs.open(pidfile, std::fstream::in);
+ if (!pidrifs.fail())
+ {
+ // Read the PID and send signal 0 to see if the process exists.
+ errno = 0;
+ if (pidrifs >> oldpid && oldpid > 1 && (kill(oldpid, 0) == 0 || errno == EPERM))
+ {
+ quit("PID file " + pidfile + " already exists and the PID therein is valid");
+ }
+ pidrifs.close();
+ }
+
+ if (unlink(pidfile.c_str()) != 0)
+ {
+ quit("Failed to remove stale PID file: " + pidfile + ": " + std::strerror(errno));
+ }
+ }
+ else if (errno != ENOENT)
{
- quit("Failed to open specified PID file for writing");
+ quit("Failed to inspect PID file path: " + pidfile + ": " + std::strerror(errno));
+ }
+
+#ifdef O_NOFOLLOW
+ const int flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW;
+#else
+ const int flags = O_WRONLY | O_CREAT | O_EXCL;
+#endif
+ pid_fd = open(pidfile.c_str(), flags, 0644);
+ if (pid_fd < 0)
+ {
+ quit("Failed to create PID file: " + pidfile + ": " + std::strerror(errno));
}
}
// Fork the process and have the parent exit. If the process was started
@@ -65,7 +109,7 @@ void fork(const std::string & pidfile)
if (pid > 0)
{
// We're in the parent process and need to exit.
- pidofs.close();
+ close_pid_fd();
// When the exit() function is used, the program terminates without
// invoking local variables' destructors. Only global variables are
// destroyed.
@@ -86,7 +130,7 @@ void fork(const std::string & pidfile)
{
if (pid > 0)
{
- pidofs.close();
+ close_pid_fd();
exit(0);
}
else
@@ -95,11 +139,18 @@ void fork(const std::string & pidfile)
}
}
- if (! pidofs.fail())
+ if (pid_fd >= 0)
{
- int pid = ::getpid();
- pidofs << pid << std::endl;
- pidofs.close();
+ const std::string pid = std::to_string(::getpid()) + "\n";
+ const ssize_t written = write(pid_fd, pid.data(), pid.size());
+ if (written < 0)
+ {
+ quit("Failed to write PID file: " + pidfile + ": " + std::strerror(errno));
+ }
+ if (static_cast<size_t>(written) != pid.size())
+ {
+ quit("Failed to write complete PID file: " + pidfile);
+ }
}
// Close the standard streams. This decouples the daemon from the terminal
diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp
index 33c0396dc..3220246ec 100644
--- a/src/multisig/multisig_tx_builder_ringct.cpp
+++ b/src/multisig/multisig_tx_builder_ringct.cpp
@@ -254,7 +254,7 @@ static void make_tx_secret_key_seed(const crypto::secret_key& tx_secret_key_entr
rct::keyV hash_context;
hash_context.reserve(2 + sources.size());
auto hash_context_wiper = epee::misc_utils::create_scope_leave_handler([&]{
- memwipe(hash_context.data(), hash_context.size());
+ memwipe(hash_context.data(), hash_context.size() * sizeof(rct::key));
});
hash_context.emplace_back();
rct::cn_fast_hash(hash_context.back(), domain_separator.data(), domain_separator.size()); //domain sep
@@ -282,7 +282,7 @@ static void make_tx_secret_keys(const crypto::secret_key& tx_secret_key_seed,
rct::keyV hash_context;
hash_context.resize(2);
auto hash_context_wiper = epee::misc_utils::create_scope_leave_handler([&]{
- memwipe(hash_context.data(), hash_context.size());
+ memwipe(hash_context.data(), hash_context.size() * sizeof(rct::key));
});
hash_context[0] = rct::sk2rct(tx_secret_key_seed);
rct::cn_fast_hash(hash_context[1], domain_separator.data(), domain_separator.size());
diff --git a/src/net/i2p_address.cpp b/src/net/i2p_address.cpp
index e793048c0..e24e7da01 100644
--- a/src/net/i2p_address.cpp
+++ b/src/net/i2p_address.cpp
@@ -117,11 +117,15 @@ namespace net
bool i2p_address::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
{
i2p_serialized in{};
- if (in._load(src, hparent) && in.host.size() < sizeof(host_) && (in.host == unknown_host || !host_check(in.host).has_error()))
+ if (in._load(src, hparent) && in.host.size() < sizeof(host_))
{
- std::memcpy(host_, in.host.data(), in.host.size());
- std::memset(host_ + in.host.size(), 0, sizeof(host_) - in.host.size());
- return true;
+ net::canonicalize_host(in.host);
+ if (in.host == unknown_host || !host_check(in.host).has_error())
+ {
+ std::memcpy(host_, in.host.data(), in.host.size());
+ std::memset(host_ + in.host.size(), 0, sizeof(host_) - in.host.size());
+ return true;
+ }
}
static_assert(sizeof(unknown_host) <= sizeof(host_), "bad buffer size");
std::memcpy(host_, unknown_host, sizeof(unknown_host)); // include null terminator
diff --git a/src/net/tor_address.cpp b/src/net/tor_address.cpp
index 35bd8e9a2..25f9fde66 100644
--- a/src/net/tor_address.cpp
+++ b/src/net/tor_address.cpp
@@ -129,12 +129,16 @@ namespace net
bool tor_address::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
{
tor_serialized in{};
- if (in._load(src, hparent) && in.host.size() < sizeof(host_) && (in.host == unknown_host || !host_check(in.host).has_error()))
+ if (in._load(src, hparent) && in.host.size() < sizeof(host_))
{
- std::memcpy(host_, in.host.data(), in.host.size());
- std::memset(host_ + in.host.size(), 0, sizeof(host_) - in.host.size());
- port_ = in.port;
- return true;
+ net::canonicalize_host(in.host);
+ if (in.host == unknown_host || !host_check(in.host).has_error())
+ {
+ std::memcpy(host_, in.host.data(), in.host.size());
+ std::memset(host_ + in.host.size(), 0, sizeof(host_) - in.host.size());
+ port_ = in.port;
+ return true;
+ }
}
static_assert(sizeof(unknown_host) <= sizeof(host_), "bad buffer size");
std::memcpy(host_, unknown_host, sizeof(unknown_host)); // include null terminator
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index 8e3312f29..d7cbaa567 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -451,6 +451,7 @@ namespace nodetool
bool m_use_ipv6;
bool m_require_ipv4;
std::atomic<bool> is_closing;
+ std::atomic<bool> m_stop_signal_sent_once{false};
std::unique_ptr<boost::thread> mPeersLoggerThread;
//critical_section m_connections_lock;
//connections_indexed_container m_connections;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index d1f7e7cdd..91a54f43e 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -1107,28 +1107,44 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::send_stop_signal()
{
+ if (m_stop_signal_sent_once.exchange(true))
+ {
+ MDEBUG("[node] Stop signal already sent");
+ return true;
+ }
MDEBUG("[node] stopping server payload handler");
m_payload_handler.stop();
- MDEBUG("[node] sending stop signal");
+
+ MDEBUG("[node] marking net servers as stopping");
for (auto& zone : m_network_zones)
{
- const auto close_all_connections = [&, this]()
+ zone.second.m_net_server.mark_stop_signal_sent();
+ }
+
+ MDEBUG("[node] closing connections");
+ for (auto& zone : m_network_zones)
+ {
+ zone.second.m_net_server.close_server_connections();
+
+ std::list<boost::uuids::uuid> connection_ids;
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
- std::list<boost::uuids::uuid> connection_ids;
- zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) {
- connection_ids.push_back(cntxt.m_connection_id);
- return true;
- });
- for (const auto &connection_id: connection_ids)
- {
- MDEBUG("Closing connection " << connection_id);
- // We need to wait for every connection's shutdown sequence to complete before stopping the io_context.
- zone.second.m_net_server.get_config_object().close(connection_id, true/*wait_for_shutdown*/);
- MDEBUG("Closed connection " << connection_id);
- }
- };
+ connection_ids.push_back(cntxt.m_connection_id);
+ return true;
+ });
+ for (const auto &connection_id: connection_ids)
+ {
+ MDEBUG("Closing connection " << connection_id);
+ // All zone connections must finish shutting down before any shared io_context is stopped.
+ zone.second.m_net_server.get_config_object().close(connection_id, true/*wait_for_shutdown*/);
+ MDEBUG("Closed connection " << connection_id);
+ }
+ }
- zone.second.m_net_server.send_stop_signal(close_all_connections);
+ MDEBUG("[node] stopping net server io_contexts");
+ for (auto& zone : m_network_zones)
+ {
+ zone.second.m_net_server.stop_io_context();
}
MDEBUG("[node] Stop signal sent");
return true;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 4c8d54f61..61f49481e 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -9116,7 +9116,6 @@ void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_
{
const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex};
bool r = epee::net_utils::invoke_http_json("/get_random_outs", oreq, ores, *m_http_client, rpc_timeout, "POST");
- m_daemon_rpc_mutex.unlock();
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_random_outs");
THROW_WALLET_EXCEPTION_IF(ores.amount_outs.empty() , error::wallet_internal_error, "No outputs received from light wallet node. Error: " + ores.Error);
}