Skip to content

Commit 27b4165

Browse files
committed
Fix crash on exit with sentry enabled (due to openssl destroyed before sentry)
The problem is tha openssl registers OPENSSL_cleanup() as atexit handler, which called before destroying of SentryWriter, so to avoid this problem, let's destroy it explicitly. <details> <summary>stack trace example</summary> Thread 2 (Thread 0x7ffff54006c0 (LWP 24847) "clickhouse-serv"): 0 ___pthread_rwlock_rdlock (rwlock=0x0) at pthread_rwlock_rdlock.c:26 1 0x00000000164c18a9 in CRYPTO_THREAD_read_lock (lock=0x0) at threads_pthread.c:93 2 0x000000001642e6b9 in int_err_get_item (d=0x7ffff53f74e0) at err.c:192 ... 7 ossl_connect_common (cf=0x7ffff7812c80, data=0x7ffff70a4c00, nonblocking=bool_true, done=0x7ffff53f834c) at openssl.c:4486 ... 17 curl_easy_perform (data=data@entry=0x7ffff70a4c00) at easy.c:787 18 0x000000000b4c3854 in sentry__curl_send_task (_envelope=<optimized out>, _state=0x7ffff7074300) at sentry_transport_curl.c:225 19 0x000000000b4ba880 in worker_thread (data=0x7ffff70e5500) at sentry_sync.c:262 Thread 1 (Thread 0x7ffff7cb2c80 (LWP 24842) "clickhouse-serv"): 5 0x000000000b4bb0e2 in sentry__cond_wait_timeout (cv=0x7ffff70e5540, mutex=0x7ffff70e5570, msecs=250) at sentry_sync.h:332 6 sentry__bgworker_shutdown (bgw=0x7ffff70e5500, timeout=2000) at sentry_sync.c:412 7 0x000000000b4b3e95 in sentry_close () at sentry_core.c:238 8 0x000000000b4a5f1f in SentryWriter::~SentryWriter (this=0x7ffff71a1240) at SentryWriter.cpp:147 9 std::__1::default_delete<SentryWriter>::operator()[abi:v15000](SentryWriter*) const (this=0x7ffff70e5568, __ptr=0x7ffff71a1240) at unique_ptr.h:48 10 std::__1::unique_ptr<SentryWriter, std::__1::default_delete<SentryWriter> >::reset[abi:v15000](SentryWriter*) (this=0x7ffff70e5568, __p=0x0) at unique_ptr.h:305 11 std::__1::unique_ptr<SentryWriter, std::__1::default_delete<SentryWriter> >::~unique_ptr[abi:v15000]() (this=0x7ffff70e5568) at unique_ptr.h:259 12 0x00007ffff7de62e6 in __run_exit_handlers (status=0, listp=<optimized out>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108 13 0x00007ffff7de642e in __GI_exit (status=<optimized out>) at exit.c:138 14 0x00007ffff7dccd51 in __libc_start_call_main (main=main@entry=0x6111c20 <main(int, char**)>, argc=argc@entry=13, argv=argv@entry=0x7fffffffb718) at libc_start_call_main.h:74 15 0x00007ffff7dcce0c in __libc_start_main_impl (main=0x6111c20 <main(int, char**)>, argc=13, argv=0x7fffffffb718, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffb708) at libc-start.c:360 (gdb) p req.body $7 = 0x7ffff7816000 "{\"dsn\":\"...\"}\n{\"type\":\"session\",\"length\":190}\n{\"init\":true,\"sid\":\"...\",\"status\":\"exited\",\"errors\":0,\"started\":\"2024-05-08T20:29:23.253Z\",\"duration\":17.213,\"attrs\":{\"release\":\"24.5\",\"environment\":\"test\"}}" </details> P.S. Likely started happens after conversion to OpenSSL (ClickHouse#59870). Signed-off-by: Azat Khuzhin <[email protected]>
1 parent dc7f515 commit 27b4165

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

src/Daemon/BaseDaemon.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,8 @@ BaseDaemon::~BaseDaemon()
706706
}
707707

708708
signal_pipe.close();
709+
710+
SentryWriter::resetInstance();
709711
}
710712

711713

src/Daemon/SentryWriter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ SentryWriter * SentryWriter::getInstance()
7272
{
7373
return SentryWriter::instance.get();
7474
}
75+
void SentryWriter::resetInstance()
76+
{
77+
SentryWriter::instance.reset();
78+
}
7579

7680
SentryWriter::SentryWriter(Poco::Util::LayeredConfiguration & config)
7781
{
@@ -254,6 +258,7 @@ void SentryWriter::sendError(Type type, int sig_or_error, const std::string & er
254258

255259
void SentryWriter::initializeInstance(Poco::Util::LayeredConfiguration &) {}
256260
SentryWriter * SentryWriter::getInstance() { return nullptr; }
261+
void SentryWriter::resetInstance() {}
257262

258263
SentryWriter::SentryWriter(Poco::Util::LayeredConfiguration &) {}
259264
SentryWriter::~SentryWriter() = default;

src/Daemon/SentryWriter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,16 @@ class SentryWriter
2222

2323
/// Initialize static SentryWriter instance
2424
static void initializeInstance(Poco::Util::LayeredConfiguration & config);
25+
2526
/// @return nullptr if initializeInstance() was not called (i.e. for non-server) or SentryWriter object
2627
static SentryWriter * getInstance();
2728

29+
/// SentryWriter static instance should be reset explicitly to avoid
30+
/// possible use-after-free, since it may use some global objects (i.e.
31+
/// OpenSSL), while sending final statistics
32+
/// (SENTRY_SESSION_STATUS_EXITED).
33+
static void resetInstance();
34+
2835
void onSignal(
2936
int sig,
3037
const std::string & error_message,

0 commit comments

Comments
 (0)