Implement a function to remove emergency handlers when a signal is raised.

Make PCAP handlers deregister from this list when they are destructed. This avoid the signal handler calling destructed objects under very rare circumstances.
master
faluco 3 years ago committed by faluco
parent 380280b4d0
commit c9c2d6982f

@ -103,7 +103,8 @@ protected:
srslog::basic_logger& logger; srslog::basic_logger& logger;
std::atomic<bool> running = {false}; std::atomic<bool> running = {false};
static_blocking_queue<pcap_pdu_t, 1024> queue; static_blocking_queue<pcap_pdu_t, 1024> queue;
uint16_t ue_id = 0; uint16_t ue_id = 0;
int emergency_handler_id = -1;
private: private:
void pack_and_queue(uint8_t* payload, void pack_and_queue(uint8_t* payload,

@ -23,16 +23,18 @@ class nas_pcap
{ {
public: public:
nas_pcap(); nas_pcap();
void enable(); ~nas_pcap();
void enable();
uint32_t open(std::string filename_, uint32_t ue_id = 0, srsran_rat_t rat_type = srsran_rat_t::lte); uint32_t open(std::string filename_, uint32_t ue_id = 0, srsran_rat_t rat_type = srsran_rat_t::lte);
void close(); void close();
void write_nas(uint8_t* pdu, uint32_t pdu_len_bytes); void write_nas(uint8_t* pdu, uint32_t pdu_len_bytes);
private: private:
bool enable_write = false; bool enable_write = false;
std::string filename; std::string filename;
FILE* pcap_file = nullptr; FILE* pcap_file = nullptr;
uint32_t ue_id = 0; uint32_t ue_id = 0;
int emergency_handler_id = -1;
void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes); void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes);
}; };

@ -22,7 +22,7 @@ class ngap_pcap
{ {
public: public:
ngap_pcap(); ngap_pcap();
~ngap_pcap() = default; ~ngap_pcap();
ngap_pcap(const ngap_pcap& other) = delete; ngap_pcap(const ngap_pcap& other) = delete;
ngap_pcap& operator=(const ngap_pcap& other) = delete; ngap_pcap& operator=(const ngap_pcap& other) = delete;
ngap_pcap(ngap_pcap&& other) = delete; ngap_pcap(ngap_pcap&& other) = delete;
@ -36,7 +36,8 @@ public:
private: private:
bool enable_write = false; bool enable_write = false;
std::string filename; std::string filename;
FILE* pcap_file = nullptr; FILE* pcap_file = nullptr;
int emergency_handler_id = -1;
}; };
} // namespace srsran } // namespace srsran

@ -22,6 +22,7 @@ class s1ap_pcap
{ {
public: public:
s1ap_pcap(); s1ap_pcap();
~s1ap_pcap();
s1ap_pcap(const s1ap_pcap& other) = delete; s1ap_pcap(const s1ap_pcap& other) = delete;
s1ap_pcap& operator=(const s1ap_pcap& other) = delete; s1ap_pcap& operator=(const s1ap_pcap& other) = delete;
s1ap_pcap(s1ap_pcap&& other) = delete; s1ap_pcap(s1ap_pcap&& other) = delete;
@ -35,7 +36,8 @@ public:
private: private:
bool enable_write = false; bool enable_write = false;
std::string filename; std::string filename;
FILE* pcap_file = nullptr; FILE* pcap_file = nullptr;
int emergency_handler_id = -1;
}; };
} // namespace srsran } // namespace srsran

@ -17,7 +17,11 @@ using emergency_cleanup_callback = void (*)(void*);
// Add a cleanup function to be called when a kill signal is about to be delivered to the process. The handler may // Add a cleanup function to be called when a kill signal is about to be delivered to the process. The handler may
// optionally pass a pointer to identify what instance of the handler is being called. // optionally pass a pointer to identify what instance of the handler is being called.
void add_emergency_cleanup_handler(emergency_cleanup_callback callback, void* data); // Returns the id of the handler as a positive value, otherwise returns -1 on error.
int add_emergency_cleanup_handler(emergency_cleanup_callback callback, void* data);
// Removes the emergency handler with the specified id.
void remove_emergency_cleanup_handler(int id);
// Executes all registered emergency cleanup handlers. // Executes all registered emergency cleanup handlers.
void execute_emergency_cleanup_handlers(); void execute_emergency_cleanup_handlers();

@ -26,10 +26,15 @@ static void emergency_cleanup_handler(void* data)
mac_pcap_base::mac_pcap_base() : logger(srslog::fetch_basic_logger("MAC")), thread("PCAP_WRITER_MAC") mac_pcap_base::mac_pcap_base() : logger(srslog::fetch_basic_logger("MAC")), thread("PCAP_WRITER_MAC")
{ {
add_emergency_cleanup_handler(emergency_cleanup_handler, this); emergency_handler_id = add_emergency_cleanup_handler(emergency_cleanup_handler, this);
} }
mac_pcap_base::~mac_pcap_base() {} mac_pcap_base::~mac_pcap_base()
{
if (emergency_handler_id > 0) {
remove_emergency_cleanup_handler(emergency_handler_id);
}
}
void mac_pcap_base::enable(bool enable_) void mac_pcap_base::enable(bool enable_)
{ {

@ -26,7 +26,14 @@ static void emergency_cleanup_handler(void* data)
nas_pcap::nas_pcap() nas_pcap::nas_pcap()
{ {
add_emergency_cleanup_handler(emergency_cleanup_handler, this); emergency_handler_id = add_emergency_cleanup_handler(emergency_cleanup_handler, this);
}
nas_pcap::~nas_pcap()
{
if (emergency_handler_id > 0) {
remove_emergency_cleanup_handler(emergency_handler_id);
}
} }
void nas_pcap::enable() void nas_pcap::enable()

@ -26,7 +26,14 @@ static void emergency_cleanup_handler(void* data)
ngap_pcap::ngap_pcap() ngap_pcap::ngap_pcap()
{ {
add_emergency_cleanup_handler(emergency_cleanup_handler, this); emergency_handler_id = add_emergency_cleanup_handler(emergency_cleanup_handler, this);
}
ngap_pcap::~ngap_pcap()
{
if (emergency_handler_id > 0) {
remove_emergency_cleanup_handler(emergency_handler_id);
}
} }
void ngap_pcap::enable() void ngap_pcap::enable()

@ -26,7 +26,14 @@ static void emergency_cleanup_handler(void* data)
s1ap_pcap::s1ap_pcap() s1ap_pcap::s1ap_pcap()
{ {
add_emergency_cleanup_handler(emergency_cleanup_handler, this); emergency_handler_id = add_emergency_cleanup_handler(emergency_cleanup_handler, this);
}
s1ap_pcap::~s1ap_pcap()
{
if (emergency_handler_id > 0) {
remove_emergency_cleanup_handler(emergency_handler_id);
}
} }
void s1ap_pcap::enable() void s1ap_pcap::enable()

@ -11,6 +11,7 @@
*/ */
#include "srsran/support/emergency_handlers.h" #include "srsran/support/emergency_handlers.h"
#include "srsran/config.h"
#include "srsran/support/srsran_assert.h" #include "srsran/support/srsran_assert.h"
namespace { namespace {
@ -29,7 +30,7 @@ static constexpr unsigned max_handlers = 12;
static handler_instance registered_handlers[max_handlers]; static handler_instance registered_handlers[max_handlers];
static std::atomic<unsigned> num_handlers; static std::atomic<unsigned> num_handlers;
void add_emergency_cleanup_handler(emergency_cleanup_callback callback, void* data) int add_emergency_cleanup_handler(emergency_cleanup_callback callback, void* data)
{ {
// Reserve a slot in the array. // Reserve a slot in the array.
auto pos = num_handlers.fetch_add(1); auto pos = num_handlers.fetch_add(1);
@ -37,13 +38,25 @@ void add_emergency_cleanup_handler(emergency_cleanup_callback callback, void* da
// Check if we have space in the array. // Check if we have space in the array.
if (pos >= max_handlers) { if (pos >= max_handlers) {
srsran_assert(0, "Exceeded the emergency cleanup handler registered limit"); srsran_assert(0, "Exceeded the emergency cleanup handler registered limit");
return; return SRSRAN_ERROR;
} }
// Order is important here: write last the callback member as it is used to signal that the handler is valid when // Order is important here: write last the callback member as it is used to signal that the handler is valid when
// reading the array. // reading the array.
registered_handlers[pos].data.store(data); registered_handlers[pos].data.store(data);
registered_handlers[pos].callback.store(callback); registered_handlers[pos].callback.store(callback);
return pos;
}
void remove_emergency_cleanup_handler(int id)
{
if (id < 0 || static_cast<unsigned>(id) >= num_handlers) {
srsran_assert(0, "Invalid emergency handler id");
return;
}
registered_handlers[id].callback.store(nullptr);
} }
void execute_emergency_cleanup_handlers() void execute_emergency_cleanup_handlers()

Loading…
Cancel
Save