Skip to content

Commit 95cd9df

Browse files
authored
chore: update helio and improve our stack overflow resiliency (#4349)
1. Run CI/Regression tests with HELIO_STACK_CHECK=4096. This will crash if a fiber stack usage goes below this limit. 2. Increase shard queue stack size to 64KB 3. Increase fiber stack size to 40KB on Debug builds. 4. Updated helio has some changes around the TLS socket code. In addition we add a helper script to generate self-signed certificates helpful for local development work. Signed-off-by: Roman Gershman <roman@dragonflydb.io>
1 parent 28848d0 commit 95cd9df

File tree

8 files changed

+108
-9
lines changed

8 files changed

+108
-9
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ jobs:
111111
-DCMAKE_CXX_COMPILER="${{matrix.compiler.cxx}}" \
112112
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_C_COMPILER_LAUNCHER=sccache \
113113
-DCMAKE_CXX_FLAGS="${{matrix.cxx_flags}} -no-pie" -DWITH_AWS:BOOL=OFF \
114+
-DHELIO_STACK_CHECK:STRING=4096 \
114115
-L
115116
cd ${GITHUB_WORKSPACE}/build && pwd
116117
du -hcs _deps/

.github/workflows/regression-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
# -no-pie to disable address randomization so we could symbolize stacktraces
3737
cmake -B ${GITHUB_WORKSPACE}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -GNinja \
3838
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DPRINT_STACKTRACES_ON_SIGNAL=ON \
39-
-DCMAKE_CXX_FLAGS=-no-pie
39+
-DCMAKE_CXX_FLAGS=-no-pie -DHELIO_STACK_CHECK:STRING=4096
4040
4141
cd ${GITHUB_WORKSPACE}/build && ninja dragonfly
4242
pwd

src/facade/dragonfly_connection.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ void Connection::HandleRequests() {
685685
FiberSocketBase::AcceptResult aresult = socket_->Accept();
686686

687687
if (!aresult) {
688-
LOG(WARNING) << "Error handshaking " << aresult.error().message();
688+
LOG(INFO) << "Error handshaking " << aresult.error().message();
689689
return;
690690
}
691691
VLOG(1) << "TLS handshake succeeded";

src/server/dfly_main.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,12 @@ namespace {
9696
// Default stack size for fibers. We decrease it by 16 bytes because some allocators
9797
// need additional 8-16 bytes for their internal structures, thus over reserving additional
9898
// memory pages if using round sizes.
99+
#ifdef NDEBUG
99100
constexpr size_t kFiberDefaultStackSize = 32_KB - 16;
101+
#else
102+
// Increase stack size for debug builds.
103+
constexpr size_t kFiberDefaultStackSize = 40_KB - 16;
104+
#endif
100105

101106
using util::http::TlsClient;
102107

src/server/snapshot.cc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
#include "server/snapshot.h"
66

7-
#include <absl/functional/bind_front.h>
87
#include <absl/strings/match.h>
98
#include <absl/strings/str_cat.h>
109

@@ -64,13 +63,18 @@ bool SliceSnapshot::IsSnaphotInProgress() {
6463
void SliceSnapshot::Start(bool stream_journal, SnapshotFlush allow_flush) {
6564
DCHECK(!snapshot_fb_.IsJoinable());
6665

67-
auto db_cb = absl::bind_front(&SliceSnapshot::OnDbChange, this);
66+
auto db_cb = [this](DbIndex db_index, const DbSlice::ChangeReq& req) {
67+
OnDbChange(db_index, req);
68+
};
69+
6870
snapshot_version_ = db_slice_->RegisterOnChange(std::move(db_cb));
6971

7072
if (stream_journal) {
7173
auto* journal = db_slice_->shard_owner()->journal();
7274
DCHECK(journal);
73-
auto journal_cb = absl::bind_front(&SliceSnapshot::OnJournalEntry, this);
75+
auto journal_cb = [this](const journal::JournalItem& item, bool await) {
76+
OnJournalEntry(item, await);
77+
};
7478
journal_cb_id_ = journal->RegisterOnChange(std::move(journal_cb));
7579
}
7680

@@ -168,7 +172,7 @@ void SliceSnapshot::IterateBucketsFb(bool send_full_sync_cut) {
168172
}
169173

170174
PrimeTable::Cursor next =
171-
pt->TraverseBuckets(cursor, absl::bind_front(&SliceSnapshot::BucketSaveCb, this));
175+
pt->TraverseBuckets(cursor, [this](auto it) { return BucketSaveCb(it); });
172176
cursor = next;
173177
PushSerialized(false);
174178

@@ -229,7 +233,9 @@ void SliceSnapshot::SwitchIncrementalFb(LSN lsn) {
229233
FiberAtomicGuard fg;
230234
serializer_->SendFullSyncCut();
231235
}
232-
auto journal_cb = absl::bind_front(&SliceSnapshot::OnJournalEntry, this);
236+
auto journal_cb = [this](const journal::JournalItem& item, bool await) {
237+
OnJournalEntry(item, await);
238+
};
233239
journal_cb_id_ = journal->RegisterOnChange(std::move(journal_cb));
234240
PushSerialized(true);
235241
} else {

src/server/transaction.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,6 @@ void Transaction::RunCallback(EngineShard* shard) {
667667
DCHECK_EQ(shard, EngineShard::tlocal());
668668

669669
RunnableResult result;
670-
auto& db_slice = GetDbSlice(shard->shard_id());
671670
try {
672671
result = (*cb_ptr_)(this, shard);
673672

@@ -691,6 +690,7 @@ void Transaction::RunCallback(EngineShard* shard) {
691690
LOG(FATAL) << "Unexpected exception " << e.what();
692691
}
693692

693+
auto& db_slice = GetDbSlice(shard->shard_id());
694694
db_slice.OnCbFinish();
695695

696696
// Handle result flags to alter behaviour.

tools/local/gen-test-certs.sh

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/bin/bash
2+
set -e
3+
4+
SCRIPT_DIR=$(dirname "$0")
5+
ROOT_DIR=$(readlink -f "$SCRIPT_DIR/../..")
6+
GEN_DIR=$ROOT_DIR/genfiles/tls
7+
8+
9+
# genfiles/tls/ca.{crt,key} Self signed CA certificate.
10+
# genfiles/tls/dragonfly.{crt,key} A certificate with no key usage/policy restrictions.
11+
# genfiles/tls/client.{crt,key} A certificate restricted for SSL client usage.
12+
# genfiles/tls/server.{crt,key} A certificate restricted for SSL server usage.
13+
14+
: '
15+
To run dragonfly use:
16+
dragonfly --tls --tls_key_file ../genfiles/tls/server.key --tls_cert_file ../genfiles/tls/server.crt -requirepass pass
17+
18+
Or with CA (does not require password):
19+
dragonfly --tls --tls_key_file ../genfiles/tls/server.key --tls_cert_file ../genfiles/tls/server.crt \
20+
--tls_ca_cert_file ../genfiles/tls/ca.crt
21+
22+
To connect with client (without ca):
23+
openssl s_client -state -crlf -connect 127.0.0.1:6379
24+
25+
With CA:
26+
openssl s_client -state -crlf -CAfile ../genfiles/tls/ca.crt -cert ../genfiles/tls/client.crt -key ../genfiles/tls/client.key -connect 127.0.0.1:6379
27+
28+
Similarly, to connect with redis-cli (no CA):
29+
redis-cli --tls --insecure -a pass
30+
31+
With CA:
32+
redis-cli --tls --cacert ../genfiles/tls/ca.crt --cert ../genfiles/tls/client.crt --key ../genfiles/tls/client.key
33+
34+
memtier (without CA):
35+
memtier_benchmark --tls --key ../genfiles/tls/client.key --cert ../genfiles/tls/client.crt -a pass
36+
37+
memtier (with CA):
38+
memtier_benchmark --tls --key ../genfiles/tls/client.key --cert ../genfiles/tls/client.crt --cacert ../genfiles/tls/ca.crt
39+
'
40+
41+
generate_cert() {
42+
local name=$1
43+
local cn="$2"
44+
local opts="$3"
45+
46+
local keyfile=$GEN_DIR/${name}.key
47+
local certfile=$GEN_DIR/${name}.crt
48+
49+
[ -f $keyfile ] || openssl genpkey -algorithm ED25519 -out $keyfile
50+
openssl req -new -sha256 \
51+
-subj "/O=Dragonfly Test/CN=$cn" \
52+
-key $keyfile | \
53+
openssl x509 \
54+
-req -sha256 \
55+
-CA $GEN_DIR/ca.crt \
56+
-CAkey $GEN_DIR/ca.key \
57+
-CAserial $GEN_DIR/ca.txt \
58+
-CAcreateserial \
59+
-days 365 \
60+
$opts \
61+
-out $certfile
62+
}
63+
64+
mkdir -p $GEN_DIR
65+
[ -f $GEN_DIR/ca.key ] || openssl genpkey -algorithm ED25519 -out $GEN_DIR/ca.key
66+
67+
# -x509: self-signed certificate, -nodes: no password
68+
openssl req \
69+
-x509 -new -nodes -sha256 \
70+
-key $GEN_DIR/ca.key \
71+
-days 3650 \
72+
-subj '/O=Dragonfly Test/CN=Certificate Authority' \
73+
-out $GEN_DIR/ca.crt
74+
75+
cat > $GEN_DIR/openssl.cnf <<_END_
76+
[ server_cert ]
77+
keyUsage = digitalSignature, keyEncipherment
78+
nsCertType = server
79+
80+
[ client_cert ]
81+
keyUsage = digitalSignature, keyEncipherment
82+
nsCertType = client
83+
_END_
84+
85+
generate_cert server "Server-only" "-extfile $GEN_DIR/openssl.cnf -extensions server_cert"
86+
generate_cert client "Client-only" "-extfile $GEN_DIR/openssl.cnf -extensions client_cert"
87+
generate_cert dragonfly "Generic-cert"

0 commit comments

Comments
 (0)