mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 04:00:34 +00:00
Add some basic configuration checks
Avoid some segmentation faults caused by ill-formatted configuration files
This commit is contained in:
parent
a21c60ecb2
commit
cd1c9e46ba
@ -81,3 +81,23 @@ int INIReader::ValueHandler(void* user, const char* section, const char* name,
|
|||||||
reader->_values[MakeKey(section, name)] = value;
|
reader->_values[MakeKey(section, name)] = value;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool INIReader::HasSection(const std::string& section) const
|
||||||
|
{
|
||||||
|
const std::string key = MakeKey(section, "");
|
||||||
|
auto pos = _values.lower_bound(key);
|
||||||
|
if (pos == _values.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Does the key at the lower_bound pos start with "section"?
|
||||||
|
return pos->first.compare(0, key.length(), key) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool INIReader::HasValue(const std::string& section, const std::string& name) const
|
||||||
|
{
|
||||||
|
std::string key = MakeKey(section, name);
|
||||||
|
return _values.count(key);
|
||||||
|
}
|
||||||
|
@ -58,6 +58,12 @@ public:
|
|||||||
//! Get an integer (long) value from INI file, returning default_value if not found.
|
//! Get an integer (long) value from INI file, returning default_value if not found.
|
||||||
int64_t GetInteger(const std::string& section, const std::string& name, int64_t default_value);
|
int64_t GetInteger(const std::string& section, const std::string& name, int64_t default_value);
|
||||||
|
|
||||||
|
//! Return true if the given section exists (section must contain at least one name=value pair).
|
||||||
|
bool HasSection(const std::string& section) const;
|
||||||
|
|
||||||
|
//! Return true if a value exists with the given section and field names.
|
||||||
|
bool HasValue(const std::string& section, const std::string& name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string MakeKey(const std::string& section, const std::string& name);
|
static std::string MakeKey(const std::string& section, const std::string& name);
|
||||||
static int ValueHandler(void* user, const char* section, const char* name,
|
static int ValueHandler(void* user, const char* section, const char* name,
|
||||||
|
@ -83,6 +83,41 @@ ControlThread::ControlThread()
|
|||||||
{
|
{
|
||||||
configuration_ = std::make_shared<FileConfiguration>(FLAGS_c);
|
configuration_ = std::make_shared<FileConfiguration>(FLAGS_c);
|
||||||
}
|
}
|
||||||
|
// Basic configuration checks
|
||||||
|
auto aux = std::dynamic_pointer_cast<FileConfiguration>(configuration_);
|
||||||
|
conf_file_has_section_ = aux->has_section();
|
||||||
|
|
||||||
|
conf_file_has_mandatory_globals_ = (configuration_->property("GNSS-SDR.internal_fs_sps", 0) == 0 ? false : true);
|
||||||
|
|
||||||
|
const std::string empty_implementation;
|
||||||
|
std::string src_impl = configuration_->property("SignalSource.implementation", empty_implementation);
|
||||||
|
int src_count = configuration_->property("Receiver.sources_count", 1);
|
||||||
|
if (src_impl.empty() && (src_count != 1))
|
||||||
|
{
|
||||||
|
int num_src = 0;
|
||||||
|
for (int i = 0; i < src_count; i++)
|
||||||
|
{
|
||||||
|
std::string src_impl_multiple = configuration_->property("SignalSource" + std::to_string(i) + ".implementation", empty_implementation);
|
||||||
|
if (!src_impl_multiple.empty())
|
||||||
|
{
|
||||||
|
num_src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num_src != src_count)
|
||||||
|
{
|
||||||
|
src_impl = std::string("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conf_has_signal_sources_ = !src_impl.empty();
|
||||||
|
|
||||||
|
std::string pvt_impl = configuration_->property("PVT.implementation", empty_implementation);
|
||||||
|
conf_has_pvt_ = !pvt_impl.empty();
|
||||||
|
|
||||||
|
std::string obs_impl = configuration_->property("Observables.implementation", empty_implementation);
|
||||||
|
conf_has_observables_ = !obs_impl.empty();
|
||||||
|
|
||||||
|
well_formatted_configuration_ = conf_file_has_section_ && conf_file_has_mandatory_globals_ && conf_has_signal_sources_ && conf_has_observables_ && conf_has_pvt_;
|
||||||
|
|
||||||
restart_ = false;
|
restart_ = false;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -91,6 +126,12 @@ ControlThread::ControlThread()
|
|||||||
ControlThread::ControlThread(std::shared_ptr<ConfigurationInterface> configuration)
|
ControlThread::ControlThread(std::shared_ptr<ConfigurationInterface> configuration)
|
||||||
{
|
{
|
||||||
configuration_ = std::move(configuration);
|
configuration_ = std::move(configuration);
|
||||||
|
conf_file_has_section_ = true;
|
||||||
|
conf_file_has_mandatory_globals_ = true;
|
||||||
|
conf_has_signal_sources_ = true;
|
||||||
|
conf_has_observables_ = true;
|
||||||
|
conf_has_pvt_ = true;
|
||||||
|
well_formatted_configuration_ = true;
|
||||||
restart_ = false;
|
restart_ = false;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -104,6 +145,8 @@ void ControlThread::init()
|
|||||||
// Instantiates a control queue, a GNSS flowgraph, and a control message factory
|
// Instantiates a control queue, a GNSS flowgraph, and a control message factory
|
||||||
control_queue_ = std::make_shared<Concurrent_Queue<pmt::pmt_t>>();
|
control_queue_ = std::make_shared<Concurrent_Queue<pmt::pmt_t>>();
|
||||||
cmd_interface_.set_msg_queue(control_queue_); // set also the queue pointer for the telecommand thread
|
cmd_interface_.set_msg_queue(control_queue_); // set also the queue pointer for the telecommand thread
|
||||||
|
if (well_formatted_configuration_)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
flowgraph_ = std::make_shared<GNSSFlowgraph>(configuration_, control_queue_);
|
flowgraph_ = std::make_shared<GNSSFlowgraph>(configuration_, control_queue_);
|
||||||
@ -112,6 +155,12 @@ void ControlThread::init()
|
|||||||
{
|
{
|
||||||
std::cout << "Caught bad lexical cast with error " << e.what() << '\n';
|
std::cout << "Caught bad lexical cast with error " << e.what() << '\n';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flowgraph_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
stop_ = false;
|
stop_ = false;
|
||||||
processed_control_messages_ = 0;
|
processed_control_messages_ = 0;
|
||||||
applied_actions_ = 0;
|
applied_actions_ = 0;
|
||||||
@ -285,6 +334,11 @@ void ControlThread::event_dispatcher(bool &valid_event, pmt::pmt_t &msg)
|
|||||||
int ControlThread::run()
|
int ControlThread::run()
|
||||||
{
|
{
|
||||||
// Connect the flowgraph
|
// Connect the flowgraph
|
||||||
|
if (!flowgraph_)
|
||||||
|
{
|
||||||
|
print_help_at_exit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
flowgraph_->connect();
|
flowgraph_->connect();
|
||||||
@ -1145,3 +1199,37 @@ void ControlThread::keyboard_listener()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ControlThread::print_help_at_exit() const
|
||||||
|
{
|
||||||
|
std::cerr << "Error: the configuration file is not well formatted\n";
|
||||||
|
if (!conf_file_has_section_)
|
||||||
|
{
|
||||||
|
std::cerr << " * The section label has not been found if the configuration file\n"
|
||||||
|
<< " Please add the [GNSS-SDR] label at the top of your configuration file\n"
|
||||||
|
<< " A configuration example is available at https://gnss-sdr.org/my-first-fix/\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!conf_file_has_mandatory_globals_)
|
||||||
|
{
|
||||||
|
std::cerr << " * Have you forgotten to set the mandatory global parameter GNSS-SDR.internal_fs_sps in your conf file?\n"
|
||||||
|
<< " Documentation about this parameter at https://gnss-sdr.org/docs/sp-blocks/global-parameters/\n"
|
||||||
|
<< " A configuration example is available at https://gnss-sdr.org/my-first-fix/\n";
|
||||||
|
}
|
||||||
|
if (!conf_has_signal_sources_)
|
||||||
|
{
|
||||||
|
std::cerr << " * The configuration file must define at least one SignalSource.implementation\n"
|
||||||
|
<< " Documentation of SignalSource block implementations at https://gnss-sdr.org/docs/sp-blocks/signal-source/\n";
|
||||||
|
}
|
||||||
|
if (!conf_has_observables_)
|
||||||
|
{
|
||||||
|
std::cerr << " * The configuration file must define an Observables.implementation\n"
|
||||||
|
<< " Documentation of the Observables block at https://gnss-sdr.org/docs/sp-blocks/observables/\n";
|
||||||
|
}
|
||||||
|
if (!conf_has_pvt_)
|
||||||
|
{
|
||||||
|
std::cerr << " * The configuration file must define a PVT.implementation\n"
|
||||||
|
<< " Documentation of the PVT block at https://gnss-sdr.org/docs/sp-blocks/pvt/\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -153,6 +153,7 @@ private:
|
|||||||
void telecommand_listener();
|
void telecommand_listener();
|
||||||
void keyboard_listener();
|
void keyboard_listener();
|
||||||
void sysv_queue_listener();
|
void sysv_queue_listener();
|
||||||
|
void print_help_at_exit() const;
|
||||||
|
|
||||||
// default filename for assistance data
|
// default filename for assistance data
|
||||||
const std::string eph_default_xml_filename_ = "./gps_ephemeris.xml";
|
const std::string eph_default_xml_filename_ = "./gps_ephemeris.xml";
|
||||||
@ -203,6 +204,12 @@ private:
|
|||||||
unsigned int applied_actions_;
|
unsigned int applied_actions_;
|
||||||
int msqid_;
|
int msqid_;
|
||||||
|
|
||||||
|
bool well_formatted_configuration_;
|
||||||
|
bool conf_file_has_section_;
|
||||||
|
bool conf_file_has_mandatory_globals_;
|
||||||
|
bool conf_has_signal_sources_;
|
||||||
|
bool conf_has_observables_;
|
||||||
|
bool conf_has_pvt_;
|
||||||
bool receiver_on_standby_;
|
bool receiver_on_standby_;
|
||||||
bool stop_;
|
bool stop_;
|
||||||
bool restart_;
|
bool restart_;
|
||||||
|
@ -60,6 +60,12 @@ void FileConfiguration::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FileConfiguration::has_section() const
|
||||||
|
{
|
||||||
|
return ini_reader_->HasSection("GNSS-SDR");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string FileConfiguration::property(std::string property_name, std::string default_value) const
|
std::string FileConfiguration::property(std::string property_name, std::string default_value) const
|
||||||
{
|
{
|
||||||
if (overrided_->is_present(property_name))
|
if (overrided_->is_present(property_name))
|
||||||
|
@ -63,6 +63,7 @@ public:
|
|||||||
double property(std::string property_name, double default_value) const override;
|
double property(std::string property_name, double default_value) const override;
|
||||||
void set_property(std::string property_name, std::string value) override;
|
void set_property(std::string property_name, std::string value) override;
|
||||||
bool is_present(const std::string& property_name) const;
|
bool is_present(const std::string& property_name) const;
|
||||||
|
bool has_section() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
Loading…
Reference in New Issue
Block a user