aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/sighandler/async_signals_handler.cpp
diff options
context:
space:
mode:
authorAnton Samokhvalov <pg83@yandex.ru>2022-02-10 16:45:15 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:15 +0300
commit72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch)
treeda2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /library/cpp/sighandler/async_signals_handler.cpp
parent778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff)
downloadydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/sighandler/async_signals_handler.cpp')
-rw-r--r--library/cpp/sighandler/async_signals_handler.cpp314
1 files changed, 157 insertions, 157 deletions
diff --git a/library/cpp/sighandler/async_signals_handler.cpp b/library/cpp/sighandler/async_signals_handler.cpp
index 00ce1c18fb..bf4a176ff3 100644
--- a/library/cpp/sighandler/async_signals_handler.cpp
+++ b/library/cpp/sighandler/async_signals_handler.cpp
@@ -1,5 +1,5 @@
#include "async_signals_handler.h"
-
+
#include <util/system/platform.h>
#if !defined(_win_)
@@ -11,10 +11,10 @@
#include <unistd.h>
-#if defined(_linux_)
-#include <dlfcn.h>
-#endif
-
+#if defined(_linux_)
+#include <dlfcn.h>
+#endif
+
#include <util/system/atomic.h>
#include <util/system/defaults.h>
#include <util/system/event.h>
@@ -22,187 +22,187 @@
#include <util/system/spinlock.h>
#include <util/system/thread.h>
#include <util/system/yassert.h>
-#include <util/generic/hash.h>
+#include <util/generic/hash.h>
-namespace {
+namespace {
volatile int SIGNAL_PIPE_WRITE_FD = 0; // will be initialized in ctor
void WriteAllOrDie(const int fd, const void* buf, size_t bufsize) {
- size_t totalBytesWritten = 0;
-
- while (totalBytesWritten != bufsize) {
- const ssize_t result = write(fd, (const char*)buf + totalBytesWritten, bufsize - totalBytesWritten);
-
- Y_VERIFY(result >= 0 || (result == -1 && errno == EINTR), "write failed: %s (errno = %d)", strerror(errno), errno);
- totalBytesWritten += static_cast<size_t>(result);
- }
+ size_t totalBytesWritten = 0;
+
+ while (totalBytesWritten != bufsize) {
+ const ssize_t result = write(fd, (const char*)buf + totalBytesWritten, bufsize - totalBytesWritten);
+
+ Y_VERIFY(result >= 0 || (result == -1 && errno == EINTR), "write failed: %s (errno = %d)", strerror(errno), errno);
+ totalBytesWritten += static_cast<size_t>(result);
+ }
}
void PipeWriterSignalHandler(int, siginfo_t* info, void*) {
- const ui8 signum = static_cast<ui8>(info->si_signo);
-
- WriteAllOrDie(SIGNAL_PIPE_WRITE_FD, &signum, 1);
- }
-
- // Handler for the "asynchronous" unix signals (those which can occur
- // at arbitrary point of execution and have no need to be reacted on instantly
- // and/or to preserve execution context at the point of interrupt).
- //
- // Async signals -- SIGHUP, SIGUSR1 (used to cause configuration files reread for example)
- // Sync signals -- fatal errors like SIGSEGV, SIGBUS...
- class TAsyncSignalsHandler {
- private:
- TThread Thread;
- int SignalPipeReadFd;
- typedef TAutoPtr<TEventHandler> TEventHandlerPtr;
- THashMap<int, TEventHandlerPtr> Handlers;
- TRWMutex HandlersLock;
-
- TAtomic ShouldDie;
+ const ui8 signum = static_cast<ui8>(info->si_signo);
+
+ WriteAllOrDie(SIGNAL_PIPE_WRITE_FD, &signum, 1);
+ }
+
+ // Handler for the "asynchronous" unix signals (those which can occur
+ // at arbitrary point of execution and have no need to be reacted on instantly
+ // and/or to preserve execution context at the point of interrupt).
+ //
+ // Async signals -- SIGHUP, SIGUSR1 (used to cause configuration files reread for example)
+ // Sync signals -- fatal errors like SIGSEGV, SIGBUS...
+ class TAsyncSignalsHandler {
+ private:
+ TThread Thread;
+ int SignalPipeReadFd;
+ typedef TAutoPtr<TEventHandler> TEventHandlerPtr;
+ THashMap<int, TEventHandlerPtr> Handlers;
+ TRWMutex HandlersLock;
+
+ TAtomic ShouldDie;
TSystemEvent DieEvent;
- static void* ThreadFunc(void* data) {
- reinterpret_cast<TAsyncSignalsHandler*>(data)->RealThreadFunc();
-
- return nullptr;
+ static void* ThreadFunc(void* data) {
+ reinterpret_cast<TAsyncSignalsHandler*>(data)->RealThreadFunc();
+
+ return nullptr;
+ }
+
+ inline void RealThreadFunc() {
+ for (;;) {
+ ui8 signum;
+ const ssize_t bytesRead = read(SignalPipeReadFd, &signum, 1);
+
+ Y_VERIFY(bytesRead >= 0 || (bytesRead == -1 && errno == EINTR), "read failed: %s (errno = %d)", strerror(errno), errno);
+
+ if (AtomicAdd(ShouldDie, 0) != 0) {
+ DieEvent.Signal();
+
+ break;
+ }
+
+ if (bytesRead == 0) {
+ break;
+ } else if (bytesRead == -1) {
+ continue;
+ }
+
+ {
+ TReadGuard dnd(HandlersLock);
+
+ const TEventHandlerPtr* handler = Handlers.FindPtr(signum);
+ Y_VERIFY(handler && handler->Get(), "Async signal handler is not set, it's a bug!");
+ handler->Get()->Handle(signum);
+ }
+ }
}
- inline void RealThreadFunc() {
- for (;;) {
- ui8 signum;
- const ssize_t bytesRead = read(SignalPipeReadFd, &signum, 1);
-
- Y_VERIFY(bytesRead >= 0 || (bytesRead == -1 && errno == EINTR), "read failed: %s (errno = %d)", strerror(errno), errno);
-
- if (AtomicAdd(ShouldDie, 0) != 0) {
- DieEvent.Signal();
-
- break;
- }
-
- if (bytesRead == 0) {
- break;
- } else if (bytesRead == -1) {
- continue;
- }
-
- {
- TReadGuard dnd(HandlersLock);
-
- const TEventHandlerPtr* handler = Handlers.FindPtr(signum);
- Y_VERIFY(handler && handler->Get(), "Async signal handler is not set, it's a bug!");
- handler->Get()->Handle(signum);
- }
- }
- }
-
- public:
- TAsyncSignalsHandler()
- : Thread(TThread::TParams(ThreadFunc, this).SetName("sighandler"))
- , SignalPipeReadFd(0)
- , ShouldDie(0)
- {
- int filedes[2] = {-1};
+ public:
+ TAsyncSignalsHandler()
+ : Thread(TThread::TParams(ThreadFunc, this).SetName("sighandler"))
+ , SignalPipeReadFd(0)
+ , ShouldDie(0)
+ {
+ int filedes[2] = {-1};
#ifdef _linux_
- int result;
-
- {
- using pipe2_t = decltype(pipe2);
- pipe2_t* pipe2Ptr = (pipe2_t*)dlsym(RTLD_DEFAULT, "pipe2");
-
-#if defined(_musl_)
- if (!pipe2Ptr) {
- pipe2Ptr = pipe2;
- }
+ int result;
+
+ {
+ using pipe2_t = decltype(pipe2);
+ pipe2_t* pipe2Ptr = (pipe2_t*)dlsym(RTLD_DEFAULT, "pipe2");
+
+#if defined(_musl_)
+ if (!pipe2Ptr) {
+ pipe2Ptr = pipe2;
+ }
+#endif
+
+ if (pipe2Ptr) {
+ result = pipe2Ptr(filedes, O_CLOEXEC);
+ } else {
+ result = -1;
+ errno = ENOSYS;
+ }
+ }
+
+ if (result != 0 && errno == ENOSYS) { // linux older than 2.6.27 returns "not implemented"
#endif
+ Y_VERIFY(pipe(filedes) == 0, "pipe failed: %s (errno = %d)", strerror(errno), errno);
- if (pipe2Ptr) {
- result = pipe2Ptr(filedes, O_CLOEXEC);
- } else {
- result = -1;
- errno = ENOSYS;
- }
- }
-
- if (result != 0 && errno == ENOSYS) { // linux older than 2.6.27 returns "not implemented"
-#endif
- Y_VERIFY(pipe(filedes) == 0, "pipe failed: %s (errno = %d)", strerror(errno), errno);
-
- SignalPipeReadFd = filedes[0];
- SIGNAL_PIPE_WRITE_FD = filedes[1];
-
- Y_VERIFY(fcntl(SignalPipeReadFd, F_SETFD, FD_CLOEXEC) == 0, "fcntl failed: %s (errno = %d)", strerror(errno), errno);
- Y_VERIFY(fcntl(SIGNAL_PIPE_WRITE_FD, F_SETFD, FD_CLOEXEC) == 0, "fcntl failed: %s (errno = %d)", strerror(errno), errno);
+ SignalPipeReadFd = filedes[0];
+ SIGNAL_PIPE_WRITE_FD = filedes[1];
+
+ Y_VERIFY(fcntl(SignalPipeReadFd, F_SETFD, FD_CLOEXEC) == 0, "fcntl failed: %s (errno = %d)", strerror(errno), errno);
+ Y_VERIFY(fcntl(SIGNAL_PIPE_WRITE_FD, F_SETFD, FD_CLOEXEC) == 0, "fcntl failed: %s (errno = %d)", strerror(errno), errno);
#ifdef _linux_
- } else {
- Y_VERIFY(result == 0, "pipe2 failed: %s (errno = %d)", strerror(errno), errno);
- SignalPipeReadFd = filedes[0];
- SIGNAL_PIPE_WRITE_FD = filedes[1];
- }
+ } else {
+ Y_VERIFY(result == 0, "pipe2 failed: %s (errno = %d)", strerror(errno), errno);
+ SignalPipeReadFd = filedes[0];
+ SIGNAL_PIPE_WRITE_FD = filedes[1];
+ }
#endif
- Thread.Start();
- Thread.Detach();
- }
+ Thread.Start();
+ Thread.Detach();
+ }
- ~TAsyncSignalsHandler() {
- AtomicSwap(&ShouldDie, TAtomic(1));
- ui8 fakeSignal = 0;
- WriteAllOrDie(SIGNAL_PIPE_WRITE_FD, &fakeSignal, 1);
+ ~TAsyncSignalsHandler() {
+ AtomicSwap(&ShouldDie, TAtomic(1));
+ ui8 fakeSignal = 0;
+ WriteAllOrDie(SIGNAL_PIPE_WRITE_FD, &fakeSignal, 1);
- DieEvent.WaitT(TDuration::Seconds(15));
+ DieEvent.WaitT(TDuration::Seconds(15));
- /* may cause VERIFY failure in signal handler, propably we should leave it to process clean procedure
+ /* may cause VERIFY failure in signal handler, propably we should leave it to process clean procedure
close(SIGNAL_PIPE_WRITE_FD);
close(SignalPipeReadFd);
*/
+ }
+
+ bool DoInstall(int signum, TAutoPtr<TEventHandler> handler) {
+ TWriteGuard dnd(HandlersLock);
+ TEventHandlerPtr& ev = Handlers[signum];
+ const bool ret = !ev;
+
+ ev = handler;
+
+ return ret;
+ }
+
+ void Install(int signum, TAutoPtr<TEventHandler> handler) {
+ if (DoInstall(signum, handler)) {
+ struct sigaction a;
+
+ memset(&a, 0, sizeof(a));
+ a.sa_sigaction = PipeWriterSignalHandler;
+ a.sa_flags = SA_SIGINFO | SA_RESTART;
+
+ Y_VERIFY(!sigaction(signum, &a, nullptr), "sigaction failed: %s (errno = %d)", strerror(errno), errno);
+ }
}
-
- bool DoInstall(int signum, TAutoPtr<TEventHandler> handler) {
- TWriteGuard dnd(HandlersLock);
- TEventHandlerPtr& ev = Handlers[signum];
- const bool ret = !ev;
-
- ev = handler;
-
- return ret;
- }
-
- void Install(int signum, TAutoPtr<TEventHandler> handler) {
- if (DoInstall(signum, handler)) {
- struct sigaction a;
-
- memset(&a, 0, sizeof(a));
- a.sa_sigaction = PipeWriterSignalHandler;
- a.sa_flags = SA_SIGINFO | SA_RESTART;
-
- Y_VERIFY(!sigaction(signum, &a, nullptr), "sigaction failed: %s (errno = %d)", strerror(errno), errno);
- }
- }
- };
-
- // This pointer is never deleted - yeah, it's intended memory leak.
- // It is necessary to prevent problems when user's signal handler calls exit function
- // which destroys all global variables including this one.
- // It such situation we have 2 options:
- // - wait for auxiliary thread to die - which will cause dead lock
- // - destruct variable, ignoring thread - which will cause data corruption.
+ };
+
+ // This pointer is never deleted - yeah, it's intended memory leak.
+ // It is necessary to prevent problems when user's signal handler calls exit function
+ // which destroys all global variables including this one.
+ // It such situation we have 2 options:
+ // - wait for auxiliary thread to die - which will cause dead lock
+ // - destruct variable, ignoring thread - which will cause data corruption.
TAsyncSignalsHandler* SIGNALS_HANDLER = nullptr;
-}
+}
void SetAsyncSignalHandler(int signum, TAutoPtr<TEventHandler> handler) {
static TAtomic lock;
-
+
if (Y_UNLIKELY(SIGNALS_HANDLER == nullptr)) {
TGuard<TAtomic> dnd(lock);
-
+
if (SIGNALS_HANDLER == nullptr) {
// NEVERS GETS DESTROYED
SIGNALS_HANDLER = new TAsyncSignalsHandler();
}
}
-
+
SIGNALS_HANDLER->Install(signum, handler);
}
@@ -218,25 +218,25 @@ namespace {
template <typename TFunc>
class TFunctionEventHandler: public TEventHandler {
TFunc Func;
-
+
public:
TFunctionEventHandler(TFunc func) {
if (func)
Func = func;
- }
+ }
int Handle(int signum) override {
- if (Func) {
- Func(signum);
- }
-
+ if (Func) {
+ Func(signum);
+ }
+
return 0;
}
};
}
void SetAsyncSignalHandler(int signum, void (*handler)(int)) {
- SetAsyncSignalHandler(signum, new TFunctionEventHandler<void (*)(int)>(handler));
+ SetAsyncSignalHandler(signum, new TFunctionEventHandler<void (*)(int)>(handler));
}
void SetAsyncSignalFunction(int signum, std::function<void(int)> func) {