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.
This commit is contained in:
faluco 2022-02-02 12:23:23 +01:00 committed by faluco
parent 380280b4d0
commit c9c2d6982f
10 changed files with 66 additions and 17 deletions

View File

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

View File

@ -23,16 +23,18 @@ class nas_pcap
{
public:
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);
void close();
void write_nas(uint8_t* pdu, uint32_t pdu_len_bytes);
void close();
void write_nas(uint8_t* pdu, uint32_t pdu_len_bytes);
private:
bool enable_write = false;
std::string filename;
FILE* pcap_file = nullptr;
uint32_t ue_id = 0;
FILE* pcap_file = nullptr;
uint32_t ue_id = 0;
int emergency_handler_id = -1;
void pack_and_write(uint8_t* pdu, uint32_t pdu_len_bytes);
};

View File

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

View File

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

View File

@ -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
// 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.
void execute_emergency_cleanup_handlers();

View File

@ -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")
{
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_)
{

View File

@ -26,7 +26,14 @@ static void emergency_cleanup_handler(void* data)
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()

View File

@ -26,7 +26,14 @@ static void emergency_cleanup_handler(void* data)
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()

View File

@ -26,7 +26,14 @@ static void emergency_cleanup_handler(void* data)
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()

View File

@ -11,6 +11,7 @@
*/
#include "srsran/support/emergency_handlers.h"
#include "srsran/config.h"
#include "srsran/support/srsran_assert.h"
namespace {
@ -29,7 +30,7 @@ static constexpr unsigned max_handlers = 12;
static handler_instance registered_handlers[max_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.
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.
if (pos >= max_handlers) {
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
// reading the array.
registered_handlers[pos].data.store(data);
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()