mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-10-31 23:26:22 +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;
|
||||
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.
|
||||
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:
|
||||
static std::string MakeKey(const std::string& section, const std::string& 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);
|
||||
}
|
||||
// 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;
|
||||
init();
|
||||
}
|
||||
@ -91,6 +126,12 @@ ControlThread::ControlThread()
|
||||
ControlThread::ControlThread(std::shared_ptr<ConfigurationInterface> 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;
|
||||
init();
|
||||
}
|
||||
@ -104,6 +145,8 @@ void ControlThread::init()
|
||||
// Instantiates a control queue, a GNSS flowgraph, and a control message factory
|
||||
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
|
||||
if (well_formatted_configuration_)
|
||||
{
|
||||
try
|
||||
{
|
||||
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';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flowgraph_ = nullptr;
|
||||
}
|
||||
|
||||
stop_ = false;
|
||||
processed_control_messages_ = 0;
|
||||
applied_actions_ = 0;
|
||||
@ -285,6 +334,11 @@ void ControlThread::event_dispatcher(bool &valid_event, pmt::pmt_t &msg)
|
||||
int ControlThread::run()
|
||||
{
|
||||
// Connect the flowgraph
|
||||
if (!flowgraph_)
|
||||
{
|
||||
print_help_at_exit();
|
||||
return 0;
|
||||
}
|
||||
try
|
||||
{
|
||||
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 keyboard_listener();
|
||||
void sysv_queue_listener();
|
||||
void print_help_at_exit() const;
|
||||
|
||||
// default filename for assistance data
|
||||
const std::string eph_default_xml_filename_ = "./gps_ephemeris.xml";
|
||||
@ -203,6 +204,12 @@ private:
|
||||
unsigned int applied_actions_;
|
||||
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 stop_;
|
||||
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
|
||||
{
|
||||
if (overrided_->is_present(property_name))
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
double property(std::string property_name, double default_value) const override;
|
||||
void set_property(std::string property_name, std::string value) override;
|
||||
bool is_present(const std::string& property_name) const;
|
||||
bool has_section() const;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
Loading…
Reference in New Issue
Block a user