SimGrid (3.31.1) NOT RELEASED YET (v3.32 expected June 21. 2022, 09:13 UTC)
+S4U:
+ - Added the xbt_enforce macro. This has the same syntax as xbt_assert. The only difference is that an AssertionError
+ exception is thrown if the condition is not satisfied, instead of calling abort().
+
Python:
- Added the following bindings / examples:
- Comm (now 100% covers the C++ interface):
- Engine.host_by_name [example: examples/python/comm-host2host/]
- Engine.mailbox_by_name_or_create [example: examples/python/comm-pingpong/]
- Mailbox: Mailbox.ready [example: examples/python/comm-ready/]
+ - Added an AssertionError exception that may be thrown in case of error. For instance, creating tow hosts with the
+ same name will now throw this exception instead of killing the interpreter.
Platform description & visualization:
- More robust sanity checks for platforms, to reject unallowed topologies with
include include/xbt/Extendable.hpp
include include/xbt/PropertyHolder.hpp
include include/xbt/asserts.h
+include include/xbt/asserts.hpp
include include/xbt/automaton.h
include include/xbt/automaton.hpp
include include/xbt/backtrace.hpp
DECLARE_SIMGRID_EXCEPTION(ParseError, PARSE_ERROR_CONSTRUCTOR);
#undef PARSE_ERROR_CONSTRUCTOR
+/** Exception raised by xbt_enforce, when an assertion is not satisfied */
+DECLARE_SIMGRID_EXCEPTION(AssertionError);
+
#undef DECLARE_SIMGRID_EXCEPTION
class XBT_PUBLIC ForcefulKillException {
--- /dev/null
+/* Copyright (c) 2016-2022. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef SIMGRID_XBT_ASSERTS_HPP
+#define SIMGRID_XBT_ASSERTS_HPP
+
+#include <simgrid/Exception.hpp>
+
+/**
+ * @brief Those are the SimGrid version of the good ol' assert macro.
+ *
+ * You can pass them a format message and arguments, just as if it where a printf.
+ *
+ * If the statement evaluates to false, then a simgrid::AsertionError is thrown.
+ * This is identical to the xbt_assert macro, except that an exception is thrown instead of calling abort().
+ *
+ * Unlike the standard assert, xbt_enforce is never disabled, even if the macro NDEBUG is defined at compile time.
+ * Note however that this macro should *not* be used with a condition that has side effects, since the exception can be
+ * caught and ignored.
+ */
+/** @brief The condition which failed will be displayed.
+ @hideinitializer */
+#define xbt_enforce(...) \
+ _XBT_IF_ONE_ARG(_xbt_enforce_ARG1, _xbt_enforce_ARGN, __VA_ARGS__)(__VA_ARGS__)
+#define _xbt_enforce_ARG1(cond) _xbt_enforce_ARGN((cond), "Assertion %s failed", #cond)
+#define _xbt_enforce_ARGN(cond, ...) \
+ do { \
+ if (!(cond)) { \
+ throw simgrid::AssertionError(XBT_THROW_POINT, xbt::string_printf(__VA_ARGS__)); \
+ } \
+ } while (0)
+
+#endif
py::register_exception<simgrid::StorageFailureException>(m, "StorageFailureException");
py::register_exception<simgrid::VmFailureException>(m, "VmFailureException");
py::register_exception<simgrid::CancelException>(m, "CancelException");
+ py::register_exception<simgrid::AssertionError>(m, "AssertionError");
/* this_actor namespace */
m.def_submodule("this_actor", "Bindings of the s4u::this_actor namespace. See the C++ documentation for details.")
#include <simgrid/s4u/Host.hpp>
#include <simgrid/s4u/VirtualMachine.hpp>
+#include "xbt/asserts.hpp"
#include "src/include/simgrid/sg_config.hpp"
#include "src/kernel/EngineImpl.hpp"
#include "src/kernel/resource/CpuImpl.hpp"
XBT_DEBUG("host model: %s", host_model_name.c_str());
if (host_model_name == "compound") {
- xbt_assert(not cpu_model_name.empty(), "Set a cpu model to use with the 'compound' host model");
- xbt_assert(not network_model_name.empty(), "Set a network model to use with the 'compound' host model");
+ xbt_enforce(not cpu_model_name.empty(), "Set a cpu model to use with the 'compound' host model");
+ xbt_enforce(not network_model_name.empty(), "Set a network model to use with the 'compound' host model");
const auto* cpu_model = find_model_description(surf_cpu_model_description, cpu_model_name);
cpu_model->model_init_preparse();
surf_config_models_setup();
}
- xbt_assert(nullptr == engine->netpoint_by_name_or_null(get_name()),
+ xbt_enforce(nullptr == engine->netpoint_by_name_or_null(get_name()),
"Refusing to create a second NetZone called '%s'.", get_cname());
netpoint_ = new NetPoint(name_, NetPoint::Type::NetZone);
XBT_DEBUG("NetZone '%s' created with the id '%lu'", get_cname(), netpoint_->id());
void NetZoneImpl::add_child(NetZoneImpl* new_zone)
{
- xbt_assert(not sealed_, "Cannot add a new child to the sealed zone %s", get_cname());
+ xbt_enforce(not sealed_, "Cannot add a new child to the sealed zone %s", get_cname());
/* set the parent behavior */
hierarchy_ = RoutingMode::recursive;
children_.push_back(new_zone);
s4u::Host* NetZoneImpl::create_host(const std::string& name, const std::vector<double>& speed_per_pstate)
{
- xbt_assert(cpu_model_pm_,
+ xbt_enforce(cpu_model_pm_,
"Impossible to create host: %s. Invalid CPU model: nullptr. Have you set the parent of this NetZone: %s?",
name.c_str(), get_cname());
- xbt_assert(not sealed_, "Impossible to create host: %s. NetZone %s already sealed", name.c_str(), get_cname());
+ xbt_enforce(not sealed_, "Impossible to create host: %s. NetZone %s already sealed", name.c_str(), get_cname());
auto* host = (new resource::HostImpl(name))->set_englobing_zone(this);
hosts_[name] = host;
host->get_iface()->set_netpoint((new NetPoint(name, NetPoint::Type::Host))->set_englobing_zone(this));
s4u::Link* NetZoneImpl::create_link(const std::string& name, const std::vector<double>& bandwidths)
{
- xbt_assert(
+ xbt_enforce(
network_model_,
"Impossible to create link: %s. Invalid network model: nullptr. Have you set the parent of this NetZone: %s?",
name.c_str(), get_cname());
- xbt_assert(not sealed_, "Impossible to create link: %s. NetZone %s already sealed", name.c_str(), get_cname());
+ xbt_enforce(not sealed_, "Impossible to create link: %s. NetZone %s already sealed", name.c_str(), get_cname());
links_[name] = do_create_link(name, bandwidths)->set_englobing_zone(this);
return links_[name]->get_iface();
}
s4u::SplitDuplexLink* NetZoneImpl::create_split_duplex_link(const std::string& name,
const std::vector<double>& bandwidths)
{
- xbt_assert(
+ xbt_enforce(
network_model_,
"Impossible to create link: %s. Invalid network model: nullptr. Have you set the parent of this NetZone: %s?",
name.c_str(), get_cname());
- xbt_assert(not sealed_, "Impossible to create link: %s. NetZone %s already sealed", name.c_str(), get_cname());
+ xbt_enforce(not sealed_, "Impossible to create link: %s. NetZone %s already sealed", name.c_str(), get_cname());
auto* link_up = create_link(name + "_UP", bandwidths)->get_impl()->set_englobing_zone(this);
auto* link_down = create_link(name + "_DOWN", bandwidths)->get_impl()->set_englobing_zone(this);
s4u::Disk* NetZoneImpl::create_disk(const std::string& name, double read_bandwidth, double write_bandwidth)
{
- xbt_assert(disk_model_,
+ xbt_enforce(disk_model_,
"Impossible to create disk: %s. Invalid disk model: nullptr. Have you set the parent of this NetZone: %s?",
name.c_str(), get_cname());
- xbt_assert(not sealed_, "Impossible to create disk: %s. NetZone %s already sealed", name.c_str(), get_cname());
+ xbt_enforce(not sealed_, "Impossible to create disk: %s. NetZone %s already sealed", name.c_str(), get_cname());
auto* l = disk_model_->create_disk(name, read_bandwidth, write_bandwidth);
return l->get_iface();
NetPoint* NetZoneImpl::create_router(const std::string& name)
{
- xbt_assert(nullptr == s4u::Engine::get_instance()->netpoint_by_name_or_null(name),
+ xbt_enforce(nullptr == s4u::Engine::get_instance()->netpoint_by_name_or_null(name),
"Refusing to create a router named '%s': this name already describes a node.", name.c_str());
- xbt_assert(not sealed_, "Impossible to create router: %s. NetZone %s already sealed", name.c_str(), get_cname());
+ xbt_enforce(not sealed_, "Impossible to create router: %s. NetZone %s already sealed", name.c_str(), get_cname());
return (new NetPoint(name, NetPoint::Type::Router))->set_englobing_zone(this);
}
}
// split-duplex links
const auto* sd_link = dynamic_cast<const s4u::SplitDuplexLink*>(link.get_link());
- xbt_assert(sd_link,
+ xbt_enforce(sd_link,
"Add_route: cast to SpliDuplexLink impossible. This should not happen, please contact SimGrid team");
resource::StandardLinkImpl* link_impl;
switch (link.get_direction()) {
if (gw_dst) {
XBT_DEBUG("Load bypassNetzoneRoute from %s@%s to %s@%s", src->get_cname(), gw_src->get_cname(), dst->get_cname(),
gw_dst->get_cname());
- xbt_assert(not link_list.empty(), "Bypass route between %s@%s and %s@%s cannot be empty.", src->get_cname(),
+ xbt_enforce(not link_list.empty(), "Bypass route between %s@%s and %s@%s cannot be empty.", src->get_cname(),
gw_src->get_cname(), dst->get_cname(), gw_dst->get_cname());
- xbt_assert(bypass_routes_.find({src, dst}) == bypass_routes_.end(),
+ xbt_enforce(bypass_routes_.find({src, dst}) == bypass_routes_.end(),
"The bypass route between %s@%s and %s@%s already exists.", src->get_cname(), gw_src->get_cname(),
dst->get_cname(), gw_dst->get_cname());
} else {
XBT_DEBUG("Load bypassRoute from %s to %s", src->get_cname(), dst->get_cname());
- xbt_assert(not link_list.empty(), "Bypass route between %s and %s cannot be empty.", src->get_cname(),
+ xbt_enforce(not link_list.empty(), "Bypass route between %s and %s cannot be empty.", src->get_cname(),
dst->get_cname());
- xbt_assert(bypass_routes_.find({src, dst}) == bypass_routes_.end(),
+ xbt_enforce(bypass_routes_.find({src, dst}) == bypass_routes_.end(),
"The bypass route between %s and %s already exists.", src->get_cname(), dst->get_cname());
}
const NetZoneImpl* src_as = src->get_englobing_zone();
const NetZoneImpl* dst_as = dst->get_englobing_zone();
- xbt_assert(src_as, "Host %s must be in a netzone", src->get_cname());
- xbt_assert(dst_as, "Host %s must be in a netzone", dst->get_cname());
+ xbt_enforce(src_as, "Host %s must be in a netzone", src->get_cname());
+ xbt_enforce(dst_as, "Host %s must be in a netzone", dst->get_cname());
/* (2) find the path to the root routing component */
std::vector<NetZoneImpl*> path_src;
if (*src_ancestor == *dst_ancestor) { // src is the ancestor of dst, or the contrary
*common_ancestor = *src_ancestor;
} else {
- xbt_assert(parent != nullptr);
+ xbt_enforce(parent != nullptr);
*common_ancestor = parent;
}
}
/* Not in the same netzone, no bypass. We'll have to find our path between the netzones recursively */
common_ancestor->get_local_route(src_ancestor->netpoint_, dst_ancestor->netpoint_, &route, latency);
- xbt_assert((route.gw_src_ != nullptr) && (route.gw_dst_ != nullptr), "Bad gateways for route from '%s' to '%s'.",
+ xbt_enforce((route.gw_src_ != nullptr) && (route.gw_dst_ != nullptr), "Bad gateways for route from '%s' to '%s'.",
src->get_cname(), dst->get_cname());
/* If source gateway is not our source, we have to recursively find our way up to this point */
void NetZoneImpl::set_parent(NetZoneImpl* parent)
{
- xbt_assert(not sealed_, "Impossible to set parent to an already sealed NetZone(%s)", this->get_cname());
+ xbt_enforce(not sealed_, "Impossible to set parent to an already sealed NetZone(%s)", this->get_cname());
parent_ = parent;
netpoint_->set_englobing_zone(parent_);
if (parent) {
void NetZoneImpl::set_network_model(std::shared_ptr<resource::NetworkModel> netmodel)
{
- xbt_assert(not sealed_, "Impossible to set network model to an already sealed NetZone(%s)", this->get_cname());
+ xbt_enforce(not sealed_, "Impossible to set network model to an already sealed NetZone(%s)", this->get_cname());
network_model_ = std::move(netmodel);
}
void NetZoneImpl::set_cpu_vm_model(std::shared_ptr<resource::CpuModel> cpu_model)
{
- xbt_assert(not sealed_, "Impossible to set CPU model to an already sealed NetZone(%s)", this->get_cname());
+ xbt_enforce(not sealed_, "Impossible to set CPU model to an already sealed NetZone(%s)", this->get_cname());
cpu_model_vm_ = std::move(cpu_model);
}
void NetZoneImpl::set_cpu_pm_model(std::shared_ptr<resource::CpuModel> cpu_model)
{
- xbt_assert(not sealed_, "Impossible to set CPU model to an already sealed NetZone(%s)", this->get_cname());
+ xbt_enforce(not sealed_, "Impossible to set CPU model to an already sealed NetZone(%s)", this->get_cname());
cpu_model_pm_ = std::move(cpu_model);
}
void NetZoneImpl::set_disk_model(std::shared_ptr<resource::DiskModel> disk_model)
{
- xbt_assert(not sealed_, "Impossible to set disk model to an already sealed NetZone(%s)", this->get_cname());
+ xbt_enforce(not sealed_, "Impossible to set disk model to an already sealed NetZone(%s)", this->get_cname());
disk_model_ = std::move(disk_model);
}
void NetZoneImpl::set_host_model(std::shared_ptr<resource::HostModel> host_model)
{
- xbt_assert(not sealed_, "Impossible to set host model to an already sealed NetZone(%s)", this->get_cname());
+ xbt_enforce(not sealed_, "Impossible to set host model to an already sealed NetZone(%s)", this->get_cname());
host_model_ = std::move(host_model);
}
const NetZoneImpl* NetZoneImpl::get_netzone_recursive(const NetPoint* netpoint) const
{
- xbt_assert(netpoint && netpoint->is_netzone(), "Netpoint %s must be of the type NetZone",
+ xbt_enforce(netpoint && netpoint->is_netzone(), "Netpoint %s must be of the type NetZone",
netpoint ? netpoint->get_cname() : "nullptr");
if (netpoint == netpoint_)
#include "xbt/graph.h"
#include "xbt/log.h"
#include "xbt/sysdep.h"
+#include "xbt/asserts.hpp"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ker_routing_generic, ker_routing, "Kernel Generic Routing");
auto* result = new Route();
if (hierarchy == RoutingMode::recursive) {
- xbt_assert(gw_src && gw_dst, "nullptr is obviously a deficient gateway");
+ xbt_enforce(gw_src && gw_dst, "nullptr is obviously a deficient gateway");
result->gw_src_ = gw_src;
result->gw_dst_ = gw_dst;
void RoutedZone::get_route_check_params(const NetPoint* src, const NetPoint* dst) const
{
- xbt_assert(src, "Cannot have a route with (nullptr) source");
- xbt_assert(dst, "Cannot have a route with (nullptr) destination");
+ xbt_enforce(src, "Cannot have a route with (nullptr) source");
+ xbt_enforce(dst, "Cannot have a route with (nullptr) destination");
const NetZoneImpl* src_as = src->get_englobing_zone();
const NetZoneImpl* dst_as = dst->get_englobing_zone();
- xbt_assert(src_as == dst_as,
+ xbt_enforce(src_as == dst_as,
"Internal error: %s@%s and %s@%s are not in the same netzone as expected. Please report that bug.",
src->get_cname(), src_as->get_cname(), dst->get_cname(), dst_as->get_cname());
- xbt_assert(this == dst_as,
+ xbt_enforce(this == dst_as,
"Internal error: route destination %s@%s is not in netzone %s as expected (route source: "
"%s@%s). Please report that bug.",
src->get_cname(), dst->get_cname(), src_as->get_cname(), dst_as->get_cname(), get_cname());
if (not gw_dst || not gw_src) {
XBT_DEBUG("Load Route from \"%s\" to \"%s\"", srcName, dstName);
- xbt_assert(not link_list.empty(), "Empty route (between %s and %s) forbidden.", srcName, dstName);
- xbt_assert(not src->is_netzone(),
+ xbt_enforce(not link_list.empty(), "Empty route (between %s and %s) forbidden.", srcName, dstName);
+ xbt_enforce(not src->is_netzone(),
"When defining a route, src cannot be a netzone such as '%s'. Did you meant to have a NetzoneRoute?",
srcName);
- xbt_assert(not dst->is_netzone(),
+ xbt_enforce(not dst->is_netzone(),
"When defining a route, dst cannot be a netzone such as '%s'. Did you meant to have a NetzoneRoute?",
dstName);
NetZoneImpl::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, get_link_list_impl(link_list, false));
} else {
XBT_DEBUG("Load NetzoneRoute from %s@%s to %s@%s", srcName, gw_src->get_cname(), dstName, gw_dst->get_cname());
- xbt_assert(src->is_netzone(), "When defining a NetzoneRoute, src must be a netzone but '%s' is not", srcName);
- xbt_assert(dst->is_netzone(), "When defining a NetzoneRoute, dst must be a netzone but '%s' is not", dstName);
+ xbt_enforce(src->is_netzone(), "When defining a NetzoneRoute, src must be a netzone but '%s' is not", srcName);
+ xbt_enforce(dst->is_netzone(), "When defining a NetzoneRoute, dst must be a netzone but '%s' is not", dstName);
- xbt_assert(gw_src->is_host() || gw_src->is_router(),
+ xbt_enforce(gw_src->is_host() || gw_src->is_router(),
"When defining a NetzoneRoute, gw_src must be a host or a router but '%s' is not.", srcName);
- xbt_assert(gw_dst->is_host() || gw_dst->is_router(),
+ xbt_enforce(gw_dst->is_host() || gw_dst->is_router(),
"When defining a NetzoneRoute, gw_dst must be a host or a router but '%s' is not.", dstName);
- xbt_assert(gw_src != gw_dst, "Cannot define a NetzoneRoute from '%s' to itself", gw_src->get_cname());
+ xbt_enforce(gw_src != gw_dst, "Cannot define a NetzoneRoute from '%s' to itself", gw_src->get_cname());
- xbt_assert(src, "Cannot add a route from %s@%s to %s@%s: %s does not exist.", srcName, gw_src->get_cname(), dstName,
+ xbt_enforce(src, "Cannot add a route from %s@%s to %s@%s: %s does not exist.", srcName, gw_src->get_cname(), dstName,
gw_dst->get_cname(), srcName);
- xbt_assert(dst, "Cannot add a route from %s@%s to %s@%s: %s does not exist.", srcName, gw_src->get_cname(), dstName,
+ xbt_enforce(dst, "Cannot add a route from %s@%s to %s@%s: %s does not exist.", srcName, gw_src->get_cname(), dstName,
gw_dst->get_cname(), dstName);
- xbt_assert(not link_list.empty(), "Empty route (between %s@%s and %s@%s) forbidden.", srcName, gw_src->get_cname(),
+ xbt_enforce(not link_list.empty(), "Empty route (between %s@%s and %s@%s) forbidden.", srcName, gw_src->get_cname(),
dstName, gw_dst->get_cname());
const auto* netzone_src = get_netzone_recursive(src);
- xbt_assert(netzone_src->is_component_recursive(gw_src),
+ xbt_enforce(netzone_src->is_component_recursive(gw_src),
"Invalid NetzoneRoute from %s@%s to %s@%s: gw_src %s belongs to %s, not to %s.", srcName,
gw_src->get_cname(), dstName, gw_dst->get_cname(), gw_src->get_cname(),
gw_src->get_englobing_zone()->get_cname(), srcName);
const auto* netzone_dst = get_netzone_recursive(dst);
- xbt_assert(netzone_dst->is_component_recursive(gw_dst),
+ xbt_enforce(netzone_dst->is_component_recursive(gw_dst),
"Invalid NetzoneRoute from %s@%s to %s@%s: gw_dst %s belongs to %s, not to %s.", srcName,
gw_src->get_cname(), dstName, gw_dst->get_cname(), gw_dst->get_cname(),
gw_dst->get_englobing_zone()->get_cname(), dst->get_cname());
CancelException::~CancelException() = default;
TracingError::~TracingError() = default;
ParseError::~ParseError() = default;
+AssertionError::~AssertionError() = default;
ForcefulKillException::~ForcefulKillException() = default;
void ForcefulKillException::do_throw()
#include <simgrid/s4u/Engine.hpp>
#include <simgrid/s4u/Host.hpp>
+#include "xbt/asserts.hpp"
#include "src/kernel/EngineImpl.hpp"
#include "src/kernel/resource/VirtualMachineImpl.hpp"
************/
HostImpl::HostImpl(const std::string& name) : piface_(this), name_(name)
{
- xbt_assert(s4u::Host::by_name_or_null(name_) == nullptr, "Refusing to create a second host named '%s'.", get_cname());
+ xbt_enforce(s4u::Host::by_name_or_null(name_) == nullptr, "Refusing to create a second host named '%s'.", get_cname());
}
HostImpl::~HostImpl()
#include <simgrid/s4u.hpp>
#include <vector>
+#include <iostream>
static void runner()
{
argv[0], argv[0]);
const char* platform_file = argv[1];
- e.load_platform(platform_file);
- simgrid::s4u::Actor::create("actor", e.host_by_name("c1_0"), runner);
+ try {
+ e.load_platform(platform_file);
+ simgrid::s4u::Actor::create("actor", e.host_by_name("c1_0"), runner);
+ e.run();
+ }
+ catch (simgrid::AssertionError& e) {
+ std::cout << e.what() << "\n";
+ }
- e.run();
return 0;
}
-! expect signal SIGIOT
$ $VALGRIND_NO_LEAK_CHECK ${bindir:=.}/issue71 ${srcdir:=.}/platform_bad.xml "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n" --log=no_loc
> [ 0.000000] (0:maestro@) Configuration change: Set 'host/model' to 'ptask_L07'
> [ 0.000000] (0:maestro@) Switching to the L07 model to handle parallel tasks.
-> [ 0.000000] (0:maestro@) Invalid NetzoneRoute from cluster1@router_c2 to cluster2@router_c1: gw_src router_c2 belongs to cluster2, not to cluster1.
+> Invalid NetzoneRoute from cluster1@router_c2 to cluster2@router_c1: gw_src router_c2 belongs to cluster2, not to cluster1.