File indexing completed on 2025-01-05 04:37:31
0001 /* 0002 SPDX-FileCopyrightText: 2010 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef BT_SIGNALCATCHER_H 0008 #define BT_SIGNALCATCHER_H 0009 0010 #ifndef Q_WS_WIN 0011 0012 #include <QObject> 0013 #include <QSocketNotifier> 0014 #include <ktorrent_export.h> 0015 #include <setjmp.h> 0016 #include <signal.h> 0017 #include <util/error.h> 0018 0019 namespace bt 0020 { 0021 /** 0022 Variable used to jump from the SIGBUS handler back to the place which triggered the SIGBUS. 0023 */ 0024 extern KTORRENT_EXPORT sigjmp_buf sigbus_env; 0025 0026 /** 0027 * Protects against SIGBUS errors when doing mmapped IO 0028 **/ 0029 class KTORRENT_EXPORT BusErrorGuard 0030 { 0031 public: 0032 BusErrorGuard(); 0033 virtual ~BusErrorGuard(); 0034 }; 0035 0036 /** 0037 Exception throw when a SIGBUS is caught. 0038 */ 0039 class KTORRENT_EXPORT BusError : public bt::Error 0040 { 0041 public: 0042 BusError(bool write_operation); 0043 ~BusError() override; 0044 0045 /// Whether or not the SIGBUS was triggered by a write operation 0046 bool write_operation; 0047 }; 0048 0049 /** 0050 * Class to handle UNIX signals (not Qt ones) 0051 */ 0052 class KTORRENT_EXPORT SignalCatcher : public QObject 0053 { 0054 Q_OBJECT 0055 public: 0056 SignalCatcher(QObject *parent = nullptr); 0057 ~SignalCatcher() override; 0058 0059 /** 0060 * Catch a UNIX signal 0061 * @param sig SIGINT, SIGTERM or some other signal 0062 * @return true upon success, false otherwise 0063 **/ 0064 bool catchSignal(int sig); 0065 0066 private Q_SLOTS: 0067 void handleInput(int fd); 0068 0069 private: 0070 static void signalHandler(int sig, siginfo_t *siginfo, void *ptr); 0071 0072 Q_SIGNALS: 0073 /// Emitted when a 0074 void triggered(); 0075 0076 private: 0077 QSocketNotifier *notifier; 0078 static int signal_received_pipe[2]; 0079 }; 0080 } 0081 0082 /// Before writing to memory mapped data, call this macro to ensure that SIGBUS signals are caught and properly dealt with 0083 #define BUS_ERROR_WPROTECT() \ 0084 BusErrorGuard bus_error_guard; \ 0085 if (sigsetjmp(bt::sigbus_env, 1)) \ 0086 throw bt::BusError(true) 0087 0088 /// Before reading from memory mapped data, call this macro to ensure that SIGBUS signals are caught and properly dealt with 0089 #define BUS_ERROR_RPROTECT() \ 0090 BusErrorGuard bus_error_guard; \ 0091 if (sigsetjmp(bt::sigbus_env, 1)) \ 0092 throw bt::BusError(false) 0093 0094 #endif 0095 0096 #endif // BT_SIGNALCATCHER_H