Skip to content

Commit 3a3e21d

Browse files
committed
Merge #14687: zmq: enable tcp keepalive
c276df7 zmq: enable tcp keepalive (mruddy) Pull request description: This addresses bitcoin/bitcoin#12754. These changes enable node operators to address the silent dropping (by network middle boxes) of long-lived low-activity ZMQ TCP connections via further operating system level TCP keepalive configuration. For example, ZMQ sockets that publish block hashes can be affected in this way due to the length of time it sometimes takes between finding blocks (e.g.- sometimes more than an hour). Prior to this patch, operating system level TCP keepalive configurations would not take effect since the SO_KEEPALIVE option was not enabled on the underlying socket. There are additional ZMQ socket options related to TCP keepalive that can be set. However, I decided not to implement those options in this changeset because doing so would require adding additional bitcoin node configuration options, and would not yield a better outcome. I preferred a small, easily reviewable patch that doesn't add a bunch of new config options, with the tradeoff that the fine tuning would have to be done via well-documented operating system specific configurations. I tested this patch by running a node with: `./src/qt/bitcoin-qt -regtest -txindex -datadir=/tmp/node -zmqpubhashblock=tcp://127.0.0.1:28332 &` and connecting to it with: `python3 ./contrib/zmq/zmq_sub.py` Without these changes, `ss -panto | grep 28332 | grep ESTAB | grep bitcoin` will report no keepalive timer information. With these changes, the output from the prior command will show keepalive timer information consistent with the configuration at the time of connection establishment, e.g.-: `timer:(keepalive,119min,0)`. I also tested with a non-TCP transport and did not witness any adverse effects: `./src/qt/bitcoin-qt -regtest -txindex -datadir=/tmp/node -zmqpubhashblock=ipc:///tmp/bitcoin.block &` ACKs for top commit: adamjonas: Just to summarize for those looking to review - as of c276df7 there are 3 tACKs (n-thumann, Haaroon, and dlogemann), 1 "looks good to me" (laanwj) with no NACKs or any show-stopping concerns raised. jonasschnelli: utACK c276df7 Tree-SHA512: b884c2c9814e97e666546a7188c48f9de9541499a11a934bd48dd16169a900c900fa519feb3b1cb7e9915fc7539aac2829c7806b5937b4e1409b4805f3ef6cd1
2 parents 48c1083 + c276df7 commit 3a3e21d

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

doc/zmq.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ ZMQ_SUBSCRIBE option set to one or either of these prefixes (for
9898
instance, just `hash`); without doing so will result in no messages
9999
arriving. Please see [`contrib/zmq/zmq_sub.py`](/contrib/zmq/zmq_sub.py) for a working example.
100100

101+
The ZMQ_PUB socket's ZMQ_TCP_KEEPALIVE option is enabled. This means that
102+
the underlying SO_KEEPALIVE option is enabled when using a TCP transport.
103+
The effective TCP keepalive values are managed through the underlying
104+
operating system configuration and must be configured prior to connection establishment.
105+
106+
For example, when running on GNU/Linux, one might use the following
107+
to lower the keepalive setting to 10 minutes:
108+
109+
sudo sysctl -w net.ipv4.tcp_keepalive_time=600
110+
111+
Setting the keepalive values appropriately for your operating environment may
112+
improve connectivity in situations where long-lived connections are silently
113+
dropped by network middle boxes.
114+
101115
## Remarks
102116

103117
From the perspective of bitcoind, the ZeroMQ socket is write-only; PUB

src/zmq/zmqpublishnotifier.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
8686
return false;
8787
}
8888

89+
const int so_keepalive_option {1};
90+
rc = zmq_setsockopt(psocket, ZMQ_TCP_KEEPALIVE, &so_keepalive_option, sizeof(so_keepalive_option));
91+
if (rc != 0) {
92+
zmqError("Failed to set SO_KEEPALIVE");
93+
zmq_close(psocket);
94+
return false;
95+
}
96+
8997
rc = zmq_bind(psocket, address.c_str());
9098
if (rc != 0)
9199
{

0 commit comments

Comments
 (0)