#ifndef SIMGRID_PUBLIC_CONFIG_H
#define SIMGRID_PUBLIC_CONFIG_H
+/* This file should only contain public declarations, mainly the definitions of SimGrid modules that were compiled in */
+
/** Define the version numbers of the used header files.
sg_version() can be used to retrieve the version of the dynamic library.
But actually, if these numbers don't match, SimGrid refuses to start (so you shouldn't have to care about sg_version() yourself) */
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@
+
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H @HAVE_SYS_TIME_H@
-
/* Whether mallocators were enabled in ccmake or not. */
#define MALLOCATOR_COMPILED_IN @MALLOCATOR_IS_WANTED@
/* Define if xbt contexts are based on our threads implementation or not */
#cmakedefine HAVE_THREAD_CONTEXTS @HAVE_THREAD_CONTEXTS@
-/* Jedule output */
-#cmakedefine HAVE_JEDULE @HAVE_JEDULE@
-
/* Tracking of latency bound */
#cmakedefine HAVE_LATENCY_BOUND_TRACKING @HAVE_LATENCY_BOUND_TRACKING@
/* Define to 1 if mmalloc is compiled in. */
#cmakedefine HAVE_MMALLOC @HAVE_MMALLOC@
-/* If Model-Checking support was requested */
-#cmakedefine HAVE_MC @HAVE_MC@
-#cmakedefine SIMGRID_HAVE_LIBSIG @SIMGRID_HAVE_LIBSIG@
+#cmakedefine HAVE_JEDULE @HAVE_JEDULE@ /* Was Jedule compiled in? */
+#cmakedefine HAVE_MC @HAVE_MC@ /* Was the model-checking compiled in? */
+#cmakedefine HAVE_NS3 @HAVE_NS3@ /* Was the NS3 support compiled in? */
+#cmakedefine HAVE_LUA @HAVE_LUA@ /* Was the Lua support compiled in? */
-#cmakedefine HAVE_VASPRINTF @HAVE_VASPRINTF@
+#cmakedefine SIMGRID_HAVE_LIBSIG @SIMGRID_HAVE_LIBSIG@
#endif /* SIMGRID_PUBLIC_CONFIG_H */
case MC_MESSAGE_ASSERTION_FAILED:
MC_report_assertion_error();
- ::exit(SIMGRID_MC_EXIT_SAFETY);
+ this->exit(SIMGRID_MC_EXIT_SAFETY);
break;
default:
return true;
}
+/** Terminate the model-checker aplication */
+void ModelChecker::exit(int status)
+{
+ // TODO, terminate the model checker politely instead of exiting rudel
+ if (process().running())
+ kill(process().pid(), SIGKILL);
+ ::exit(status);
+}
+
bool ModelChecker::handle_events()
{
char buffer[MC_MESSAGE_LENGTH];
xbt_die("Could not get exit status");
if (WIFSIGNALED(status)) {
MC_report_crash(status);
- ::exit(SIMGRID_MC_EXIT_PROGRAM_CRASH);
+ mc_model_checker->exit(SIMGRID_MC_EXIT_PROGRAM_CRASH);
}
}
{
mc_model_checker->wait_client(mc_model_checker->process());
}
+ void exit(int status);
private:
void setup_ignore();
bool handle_message(char* buffer, ssize_t size);
*/
class Member {
public:
- Member() : inheritance(false), byte_size(0), type_id(0) {}
+ Member() {}
- bool inheritance;
+ /** Whether this member represent some inherited part of the object */
+ bool inheritance = false;
+
+ /** Name of the member (if any) */
std::string name;
+
+ /** DWARF location expression for locating the location of the member */
simgrid::dwarf::DwarfExpression location_expression;
- std::size_t byte_size; // Do we really need this?
- unsigned type_id;
- simgrid::mc::Type* type;
+ std::size_t byte_size = 0; // Do we really need this?
+
+ unsigned type_id = 0;
+ simgrid::mc::Type* type = nullptr;
+
+ /** Whether the member is at a fixed offset from the base address */
bool has_offset_location() const
{
+ // Recognize the expression `DW_OP_plus_uconst(offset)`:
return location_expression.size() == 1 &&
location_expression[0].atom == DW_OP_plus_uconst;
}
- // TODO, check if this shortcut is really necessary
+ /** Get the offset of the member
+ *
+ * This is only valid is the member is at a fixed offset from the base.
+ * This is often the case (for C types, C++ type without virtual
+ * inheritance).
+ *
+ * If the location is more complex, the location expression has
+ * to be evaluated (which might need accessing the memory).
+ */
int offset() const
{
xbt_assert(this->has_offset_location());
return this->location_expression[0].number;
}
+ /** Set the location of the member as a fixed offset */
void offset(int new_offset)
{
+ // Set the expression to be `DW_OP_plus_uconst(offset)`:
Dwarf_Op op;
op.atom = DW_OP_plus_uconst;
op.number = new_offset;
this->location_expression = { op };
}
+
};
/** A type in the model-checked program */
class Type {
public:
- Type();
- Type(Type const& type) = default;
- Type& operator=(Type const&) = default;
- Type(Type&& type) = default;
- Type& operator=(Type&&) = default;
+ Type() {}
/** The DWARF TAG of the type (e.g. DW_TAG_array_type) */
- int type;
- unsigned id; /* Offset in the section (in hexadecimal form) */
+ int type = 0;
+ unsigned id = 0; /* Offset in the section (in hexadecimal form) */
std::string name; /* Name of the type */
- int byte_size; /* Size in bytes */
- int element_count; /* Number of elements for array type */
- unsigned type_id; /* DW_AT_type id */
+ int byte_size = 0; /* Size in bytes */
+ int element_count = 0; /* Number of elements for array type */
+ unsigned type_id = 0; /* DW_AT_type id */
std::vector<Member> members; /* if DW_TAG_structure_type, DW_TAG_class_type, DW_TAG_union_type*/
- int is_pointer_type;
- simgrid::mc::Type* subtype; // DW_AT_type
- simgrid::mc::Type* full_type; // The same (but more complete) type
+ simgrid::mc::Type* subtype = nullptr; // DW_AT_type
+ simgrid::mc::Type* full_type = nullptr; // The same (but more complete) type
};
-inline
-Type::Type()
-{
- this->type = 0;
- this->id = 0;
- this->byte_size = 0;
- this->element_count = 0;
- this->is_pointer_type = 0;
- this->type_id = 0;
- this->subtype = nullptr;
- this->full_type = nullptr;
-}
-
}
}
/** A variable (global or local) in the model-checked program */
class Variable {
public:
- Variable();
-
- unsigned dwarf_offset; /* Global offset of the field. */
- int global;
+ Variable() {}
+ unsigned dwarf_offset = 0; /* Global offset of the field. */
+ int global = 0;
std::string name;
- unsigned type_id;
- simgrid::mc::Type* type;
-
+ unsigned type_id = 0;
+ simgrid::mc::Type* type = nullptr;
// Use either of:
simgrid::dwarf::LocationList location_list;
- void* address;
-
- size_t start_scope;
- simgrid::mc::ObjectInformation* object_info;
+ void* address = nullptr;
+ size_t start_scope = 0;
+ simgrid::mc::ObjectInformation* object_info = nullptr;
};
-inline
-Variable::Variable()
-{
- this->dwarf_offset = 0;
- this->global = 0;
- this->type = nullptr;
- this->type_id = 0;
- this->address = nullptr;
- this->start_scope = 0;
- this->object_info = nullptr;
-}
-
}
}
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_checkpoint, mc,
"Logging specific to mc_checkpoint");
+}
+
+namespace simgrid {
+namespace mc {
+
/************************************ Free functions **************************************/
/*****************************************************************************************/
*
* @param reg Target region
*/
-static void MC_region_restore(mc_mem_region_t region)
+static void restore(mc_mem_region_t region)
{
switch(region->storage_type()) {
case simgrid::mc::StorageType::NoData:
case simgrid::mc::StorageType::Privatized:
for (auto& p : region->privatized_data())
- MC_region_restore(&p);
+ restore(&p);
break;
}
}
-}
-
-namespace simgrid {
-namespace mc {
-
#ifdef HAVE_SMPI
RegionSnapshot privatized_region(
RegionType region_type, void *start_addr, void* permanent_addr,
}
#endif
-}
-}
-
-extern "C" {
-
-static void MC_snapshot_add_region(int index, mc_snapshot_t snapshot,
+static
+void add_region(int index, mc_snapshot_t snapshot,
simgrid::mc::RegionType type,
simgrid::mc::ObjectInformation* object_info,
void *start_addr, void* permanent_addr,
return;
}
-static void MC_get_memory_regions(simgrid::mc::Process* process, mc_snapshot_t snapshot)
+static void get_memory_regions(simgrid::mc::Process* process, mc_snapshot_t snapshot)
{
const size_t n = process->object_infos.size();
snapshot->snapshot_regions.resize(n + 1);
int i = 0;
for (auto const& object_info : process->object_infos) {
- MC_snapshot_add_region(i, snapshot, simgrid::mc::RegionType::Data,
+ add_region(i, snapshot, simgrid::mc::RegionType::Data,
object_info.get(),
object_info->start_rw, object_info->start_rw,
object_info->end_rw - object_info->start_rw);
void *start_heap = heap->base;
void *end_heap = heap->breakval;
- MC_snapshot_add_region(n, snapshot, simgrid::mc::RegionType::Heap, NULL,
+ add_region(n, snapshot, simgrid::mc::RegionType::Heap, NULL,
start_heap, start_heap,
(char *) end_heap - (char *) start_heap);
snapshot->heap_bytes_used = mmalloc_get_bytes_used_remote(
*
* `dl_iterate_phdr` would be more robust but would not work in cross-process.
* */
-void MC_find_object_address(
+void find_object_address(
std::vector<simgrid::xbt::VmMap> const& maps,
simgrid::mc::ObjectInformation* result)
{
* \param ip Instruction pointer
* \return true if the variable is valid
* */
-static bool mc_valid_variable(simgrid::mc::Variable* var,
+static bool valid_variable(simgrid::mc::Variable* var,
simgrid::mc::Frame* scope,
const void *ip)
{
return true;
}
-static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame,
+static void fill_local_variables_values(mc_stack_frame_t stack_frame,
simgrid::mc::Frame* scope,
int process_index,
std::vector<s_local_variable>& result)
for(simgrid::mc::Variable& current_variable :
scope->variables) {
- if (!mc_valid_variable(¤t_variable, scope, (void *) stack_frame->ip))
+ if (!valid_variable(¤t_variable, scope, (void *) stack_frame->ip))
continue;
int region_type;
// Recursive processing of nested scopes:
for(simgrid::mc::Frame& nested_scope : scope->scopes)
- mc_fill_local_variables_values(
+ fill_local_variables_values(
stack_frame, &nested_scope, process_index, result);
}
-static std::vector<s_local_variable> MC_get_local_variables_values(
+static std::vector<s_local_variable> get_local_variables_values(
std::vector<s_mc_stack_frame_t>& stack_frames, int process_index)
{
std::vector<s_local_variable> variables;
for (s_mc_stack_frame_t& stack_frame : stack_frames)
- mc_fill_local_variables_values(&stack_frame, stack_frame.frame, process_index, variables);
+ fill_local_variables_values(&stack_frame, stack_frame.frame, process_index, variables);
return std::move(variables);
}
-static void MC_stack_frame_free_voipd(void *s)
-{
- mc_stack_frame_t stack_frame = *(mc_stack_frame_t *) s;
- delete(stack_frame);
-}
-
-static std::vector<s_mc_stack_frame_t> MC_unwind_stack_frames(mc_unw_context_t stack_context)
+static std::vector<s_mc_stack_frame_t> unwind_stack_frames(mc_unw_context_t stack_context)
{
simgrid::mc::Process* process = &mc_model_checker->process();
std::vector<s_mc_stack_frame_t> result;
return std::move(result);
};
-static std::vector<s_mc_snapshot_stack_t> MC_take_snapshot_stacks(mc_snapshot_t * snapshot)
+static std::vector<s_mc_snapshot_stack_t> take_snapshot_stacks(mc_snapshot_t * snapshot)
{
std::vector<s_mc_snapshot_stack_t> res;
&context) < 0) {
xbt_die("Could not initialise the libunwind context.");
}
- st.stack_frames = MC_unwind_stack_frames(&st.context);
- st.local_variables = MC_get_local_variables_values(st.stack_frames, stack.process_index);
+ st.stack_frames = unwind_stack_frames(&st.context);
+ st.local_variables = get_local_variables_values(st.stack_frames, stack.process_index);
st.process_index = stack.process_index;
unw_word_t sp = st.stack_frames[0].sp;
}
-static void MC_snapshot_handle_ignore(mc_snapshot_t snapshot)
+static void snapshot_handle_ignore(mc_snapshot_t snapshot)
{
xbt_assert(snapshot->process());
}
-static void MC_snapshot_ignore_restore(mc_snapshot_t snapshot)
+static void snapshot_ignore_restore(mc_snapshot_t snapshot)
{
for (auto const& ignored_data : snapshot->ignored_data)
snapshot->process()->write_bytes(
remote(ignored_data.start));
}
-static std::vector<s_fd_infos_t> MC_get_current_fds(pid_t pid)
+static std::vector<s_fd_infos_t> get_current_fds(pid_t pid)
{
const size_t fd_dir_path_size = 20;
char fd_dir_path[fd_dir_path_size];
return std::move(fds);
}
-mc_snapshot_t MC_take_snapshot(int num_state)
+mc_snapshot_t take_snapshot(int num_state)
{
XBT_DEBUG("Taking snapshot %i", num_state);
MC_EACH_SIMIX_PROCESS(process,
snapshot->enabled_processes.insert(process->pid));
- MC_snapshot_handle_ignore(snapshot);
+ snapshot_handle_ignore(snapshot);
if (_sg_mc_snapshot_fds)
- snapshot->current_fds = MC_get_current_fds(process->pid);
+ snapshot->current_fds = get_current_fds(process->pid);
const bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty;
/* Save the std heap and the writable mapped pages of libsimgrid and binary */
- MC_get_memory_regions(mc_process, snapshot);
+ get_memory_regions(mc_process, snapshot);
if (use_soft_dirty)
mc_process->reset_soft_dirty();
if (_sg_mc_visited > 0 || strcmp(_sg_mc_property_file, "")) {
snapshot->stacks =
- MC_take_snapshot_stacks(&snapshot);
+ take_snapshot_stacks(&snapshot);
if (_sg_mc_hash) {
snapshot->hash = simgrid::mc::hash(*snapshot);
} else {
snapshot->hash = 0;
}
- MC_snapshot_ignore_restore(snapshot);
+ snapshot_ignore_restore(snapshot);
if (use_soft_dirty)
mc_model_checker->parent_snapshot_ = snapshot;
return snapshot;
}
static inline
-void MC_restore_snapshot_regions(mc_snapshot_t snapshot)
+void restore_snapshot_regions(mc_snapshot_t snapshot)
{
for(std::unique_ptr<s_mc_mem_region_t> const& region : snapshot->snapshot_regions) {
// For privatized, variables we decided it was not necessary to take the snapshot:
if (region)
- MC_region_restore(region.get());
+ restore(region.get());
}
#ifdef HAVE_SMPI
}
static inline
-void MC_restore_snapshot_fds(mc_snapshot_t snapshot)
+void restore_snapshot_fds(mc_snapshot_t snapshot)
{
if (mc_mode == MC_MODE_SERVER)
xbt_die("FD snapshot not implemented in client/server mode.");
}
}
-void MC_restore_snapshot(mc_snapshot_t snapshot)
+void restore_snapshot(mc_snapshot_t snapshot)
{
XBT_DEBUG("Restore snapshot %i", snapshot->num_state);
const bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty;
- MC_restore_snapshot_regions(snapshot);
+ restore_snapshot_regions(snapshot);
if (_sg_mc_snapshot_fds)
- MC_restore_snapshot_fds(snapshot);
+ restore_snapshot_fds(snapshot);
if (use_soft_dirty)
mc_model_checker->process().reset_soft_dirty();
- MC_snapshot_ignore_restore(snapshot);
+ snapshot_ignore_restore(snapshot);
mc_model_checker->process().cache_flags = 0;
if (use_soft_dirty)
mc_model_checker->parent_snapshot_ = snapshot;
}
-mc_snapshot_t simcall_HANDLER_mc_snapshot(smx_simcall_t simcall)
-{
- return MC_take_snapshot(1);
+}
}
+extern "C"
+mc_snapshot_t simcall_HANDLER_mc_snapshot(smx_simcall_t simcall)
+{
+ return simgrid::mc::take_snapshot(1);
}
xbt_free(initial_global_state->send_diff);
initial_global_state->send_diff = NULL;
MC_print_statistics(mc_stats);
- exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
+ mc_model_checker->exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
}else if(_sg_mc_comms_determinism && (!initial_global_state->send_deterministic && !initial_global_state->recv_deterministic)) {
XBT_INFO("****************************************************");
XBT_INFO("***** Non-deterministic communications pattern *****");
xbt_free(initial_global_state->recv_diff);
initial_global_state->recv_diff = NULL;
MC_print_statistics(mc_stats);
- exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
+ mc_model_checker->exit(SIMGRID_MC_EXIT_NON_DETERMINISM);
}
}
}
MC_pre_modelcheck_comm_determinism();
initial_global_state = xbt_new0(s_mc_global_t, 1);
- initial_global_state->snapshot = MC_take_snapshot(0);
+ initial_global_state->snapshot = simgrid::mc::take_snapshot(0);
initial_global_state->initial_communications_pattern_done = 0;
initial_global_state->recv_deterministic = 1;
initial_global_state->send_deterministic = 1;
case DW_TAG_pointer_type:
case DW_TAG_reference_type:
case DW_TAG_rvalue_reference_type:
- type.is_pointer_type = 1;
break;
case DW_TAG_structure_type:
std::shared_ptr<simgrid::mc::ObjectInformation> result =
std::make_shared<simgrid::mc::ObjectInformation>();
result->file_name = name;
- MC_find_object_address(maps, result.get());
+ simgrid::mc::find_object_address(maps, result.get());
MC_dwarf_get_variables(result.get());
MC_post_process_variables(result.get());
MC_post_process_types(result.get());
start_item = xbt_fifo_get_first_item(stack);
state = (mc_state_t)xbt_fifo_get_item_content(start_item);
if(state->system_state){
- MC_restore_snapshot(state->system_state);
+ simgrid::mc::restore_snapshot(state->system_state);
if(_sg_mc_comms_determinism || _sg_mc_send_determinism)
MC_restore_communications_pattern(state);
return;
/* Restore the initial state */
- MC_restore_snapshot(initial_global_state->snapshot);
+ simgrid::mc::restore_snapshot(initial_global_state->snapshot);
/* At the moment of taking the snapshot the raw heap was set, so restoring
* it will set it back again, we have to unset it to continue */
item = xbt_fifo_get_first_item(stack);
pair = (mc_pair_t) xbt_fifo_get_item_content(item);
if(pair->graph_state->system_state){
- MC_restore_snapshot(pair->graph_state->system_state);
+ simgrid::mc::restore_snapshot(pair->graph_state->system_state);
return;
}
}
/* Restore the initial state */
- MC_restore_snapshot(initial_global_state->snapshot);
+ simgrid::mc::restore_snapshot(initial_global_state->snapshot);
/* Traverse the stack from the initial state and re-execute the transitions */
for (item = xbt_fifo_get_last_item(stack);
if(_sg_mc_visited > 0)
visited_pairs = xbt_dynar_new(sizeof(mc_visited_pair_t), NULL);
- initial_global_state->snapshot = MC_take_snapshot(0);
+ initial_global_state->snapshot = simgrid::mc::take_snapshot(0);
initial_global_state->prev_pair = 0;
unsigned int cursor = 0;
#ifdef __cplusplus
-XBT_PRIVATE void MC_find_object_address(
+namespace simgrid {
+namespace mc {
+
+XBT_PRIVATE void find_object_address(
std::vector<simgrid::xbt::VmMap> const& maps, simgrid::mc::ObjectInformation* result);
+}
+}
+
#endif
SG_END_DECL()
/* Save the initial state */
initial_global_state = xbt_new0(s_mc_global_t, 1);
- initial_global_state->snapshot = MC_take_snapshot(0);
+ initial_global_state->snapshot = simgrid::mc::take_snapshot(0);
}
static const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
-XBT_PRIVATE mc_snapshot_t MC_take_snapshot(int num_state);
-XBT_PRIVATE void MC_restore_snapshot(mc_snapshot_t);
+}
+
+#ifdef __cplusplus
+
+namespace simgrid {
+namespace mc {
+
+XBT_PRIVATE mc_snapshot_t take_snapshot(int num_state);
+XBT_PRIVATE void restore_snapshot(mc_snapshot_t);
+
+}
+}
+
+#endif
+
+extern "C" {
XBT_PRIVATE void mc_restore_page_snapshot_region(
simgrid::mc::Process* process,
state->incomplete_comm_pattern = NULL;
/* Stateful model checking */
if((_sg_mc_checkpoint > 0 && (mc_stats->expanded_states % _sg_mc_checkpoint == 0)) || _sg_mc_termination){
- state->system_state = MC_take_snapshot(state->num);
+ state->system_state = simgrid::mc::take_snapshot(state->num);
if(_sg_mc_comms_determinism || _sg_mc_send_determinism){
MC_state_copy_incomplete_communications_pattern(state);
MC_state_copy_index_communications_pattern(state);
new_state->nb_processes = xbt_dynar_length(
mc_model_checker->process().smx_process_infos);
- new_state->system_state = MC_take_snapshot(mc_stats->expanded_states);
+ new_state->system_state = simgrid::mc::take_snapshot(mc_stats->expanded_states);
new_state->num = mc_stats->expanded_states;
new_state->other_num = -1;
return new_state;
pair = xbt_new0(s_mc_visited_pair_t, 1);
pair->graph_state = graph_state;
if(pair->graph_state->system_state == NULL)
- pair->graph_state->system_state = MC_take_snapshot(pair_num);
+ pair->graph_state->system_state = simgrid::mc::take_snapshot(pair_num);
pair->heap_bytes_used = mmalloc_get_bytes_used_remote(
process->get_heap()->heaplimit,
process->get_malloc_info());
#include <cstdio>
#include <cstring>
+#include <utility>
+
#include <signal.h>
#include <poll.h>
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_main, mc, "Entry point for simgrid-mc");
-static int do_child(int socket, char** argv)
+/** Execute some code in a forked process */
+template<class F>
+static inline
+pid_t do_fork(F f)
+{
+ pid_t pid = fork();
+ if (pid < 0)
+ throw new std::system_error(errno, std::generic_category());
+ if (pid != 0)
+ return pid;
+
+ // Child-process:
+ try {
+ f();
+ std::exit(EXIT_SUCCESS);
+ }
+ catch(...) {
+ // The callback should catch exceptions:
+ abort();
+ }
+}
+
+static
+int exec_model_checked(int socket, char** argv)
{
XBT_DEBUG("Inside the child process PID=%i", (int) getpid());
// Make sure we do not outlive our parent:
sigset_t mask;
sigemptyset (&mask);
- if (sigprocmask(SIG_SETMASK, &mask, nullptr) < 0) {
- std::perror ("sigprocmask");
- return SIMGRID_MC_EXIT_ERROR;
- }
-
- if (prctl(PR_SET_PDEATHSIG, SIGHUP) != 0) {
- std::perror("simgrid-mc");
- return SIMGRID_MC_EXIT_ERROR;
- }
+ if (sigprocmask(SIG_SETMASK, &mask, nullptr) < 0)
+ throw new std::system_error(errno, std::generic_category(), "sigprocmask");
+ if (prctl(PR_SET_PDEATHSIG, SIGHUP) != 0)
+ throw new std::system_error(errno, std::generic_category(), "PR_SET_PDEATHSIG");
#endif
int res;
// Remove CLOEXEC in order to pass the socket to the exec-ed program:
int fdflags = fcntl(socket, F_GETFD, 0);
- if (fdflags == -1) {
- std::perror("simgrid-mc");
- return SIMGRID_MC_EXIT_ERROR;
- }
- if (fcntl(socket, F_SETFD, fdflags & ~FD_CLOEXEC) == -1) {
- std::perror("simgrid-mc");
- return SIMGRID_MC_EXIT_ERROR;
- }
-
- XBT_DEBUG("CLOEXEC removed on socket %i", socket);
+ if (fdflags == -1)
+ throw new std::system_error(errno, std::generic_category(), "F_GETFD");
+ if (fcntl(socket, F_SETFD, fdflags & ~FD_CLOEXEC) == -1)
+ throw new std::system_error(errno, std::generic_category(), "Remove FD_CLOEXEC");
// Set environment:
setenv(MC_ENV_VARIABLE, "1", 1);
- // Disable lazy relocation in the model-ched process.
+ // Disable lazy relocation in the model-checked process.
// We don't want the model-checked process to modify its .got.plt during
// snapshot.
setenv("LC_BIND_NOW", "1", 1);
char buffer[64];
res = std::snprintf(buffer, sizeof(buffer), "%i", socket);
if ((size_t) res >= sizeof(buffer) || res == -1)
- return SIMGRID_MC_EXIT_ERROR;
+ std::abort();
setenv(MC_ENV_SOCKET_FD, buffer, 1);
execvp(argv[1], argv+1);
- XBT_ERROR("Could not execute the child process");
- return SIMGRID_MC_EXIT_ERROR;
+
+ XBT_ERROR("Could not run the model-checked program");
+ // This is the value used by system() and popen() in this case:
+ return 127;
}
-static int do_parent(int socket, pid_t child)
+static
+std::pair<pid_t, int> create_model_checked(char** argv)
+{
+ // Create a AF_LOCAL socketpair used for exchanging messages
+ // bewteen the model-checker process (ourselves) and the model-checked
+ // process:
+ int res;
+ int sockets[2];
+ res = socketpair(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0, sockets);
+ if (res == -1)
+ throw new std::system_error(errno, std::generic_category(), "socketpair");
+
+ pid_t pid = do_fork([&] {
+ close(sockets[1]);
+ int res = exec_model_checked(sockets[0], argv);
+ XBT_DEBUG("Error in the child process creation");
+ exit(res);
+ });
+
+ // Parent (model-checker):
+ close(sockets[0]);
+ return std::make_pair(pid, sockets[1]);
+}
+
+static
+char** argvdup(int argc, char** argv)
+{
+ char** argv_copy = xbt_new(char*, argc+1);
+ std::memcpy(argv_copy, argv, sizeof(char*) * argc);
+ argv_copy[argc] = NULL;
+ return argv_copy;
+}
+
+int main(int argc, char** argv)
{
- XBT_DEBUG("Inside the parent process");
- if (mc_model_checker)
- xbt_die("MC server already present");
try {
+ if (argc < 2)
+ xbt_die("Missing arguments.\n");
+
+ _sg_do_model_check = 1;
+
+ // The initialisation function can touch argv.
+ // We need to keep the original parameters in order to pass them to the
+ // model-checked process so we make a copy of them:
+ int argc_copy = argc;
+ char** argv_copy = argvdup(argc, argv);
+ xbt_log_init(&argc_copy, argv_copy);
+ sg_config_init(&argc_copy, argv_copy);
+
+ int sock;
+ pid_t model_checked_pid;
+ std::tie(model_checked_pid, sock) = create_model_checked(argv);
+ XBT_DEBUG("Inside the parent process");
+ if (mc_model_checker)
+ xbt_die("MC server already present");
+
mc_mode = MC_MODE_SERVER;
- std::unique_ptr<simgrid::mc::Process> process(new simgrid::mc::Process(child, socket));
+ std::unique_ptr<simgrid::mc::Process> process(new simgrid::mc::Process(model_checked_pid, sock));
process->privatized(sg_cfg_get_boolean("smpi/privatize_global_variables"));
mc_model_checker = new simgrid::mc::ModelChecker(std::move(process));
mc_model_checker->start();
XBT_ERROR("Exception: %s", e.what());
return SIMGRID_MC_EXIT_ERROR;
}
-}
-
-static char** argvdup(int argc, char** argv)
-{
- char** argv_copy = xbt_new(char*, argc+1);
- std::memcpy(argv_copy, argv, sizeof(char*) * argc);
- argv_copy[argc] = NULL;
- return argv_copy;
-}
-
-int main(int argc, char** argv)
-{
- _sg_do_model_check = 1;
-
- // We need to keep the original parameters in order to pass them to the
- // model-checked process:
- int argc_copy = argc;
- char** argv_copy = argvdup(argc, argv);
- xbt_log_init(&argc_copy, argv_copy);
- sg_config_init(&argc_copy, argv_copy);
-
- if (argc < 2)
- xbt_die("Missing arguments.\n");
-
- // Create a AF_LOCAL socketpair:
- int res;
-
- int sockets[2];
- res = socketpair(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0, sockets);
- if (res == -1) {
- perror("simgrid-mc");
- return SIMGRID_MC_EXIT_ERROR;
- }
-
- XBT_DEBUG("Created socketpair");
-
- pid_t pid = fork();
- if (pid < 0) {
- perror("simgrid-mc");
+ catch(...) {
+ XBT_ERROR("Unknown exception");
return SIMGRID_MC_EXIT_ERROR;
- } else if (pid == 0) {
- close(sockets[1]);
- int res = do_child(sockets[0], argv);
- XBT_DEBUG("Error in the child process creation");
- return res;
- } else {
- close(sockets[0]);
- return do_parent(sockets[1], pid);
}
-
- return 0;
}
#ifndef SIMGRID_PORTABLE_H
#define SIMGRID_PORTABLE_H
-#include "src/internal_config.h"
+#include "simgrid_config.h" /* what was compiled in? */
+#include "src/internal_config.h" /* some information about the environment */
+
#include "xbt/base.h"
#include "xbt/misc.h"
#ifdef _XBT_WIN32
#include "instr/instr_interface.h"
#include "simgrid/simix.h"
#include "simgrid/sg_config.h"
+#include "simgrid_config.h" /* what was compiled in? */
#ifdef HAVE_SMPI
#include "smpi/smpi_interface.h"
#endif
/* 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. */
+#include "src/portable.h"
#include "surf_private.h"
#include "surf_interface.hpp"
#include "network_interface.hpp"
#include "virtual_machine.hpp"
#include "src/instr/instr_private.h" // TRACE_is_enabled(). FIXME: remove by subscribing tracing to the surf signals
-
XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
"Logging specific to SURF (kernel)");
return -1;
}
-static XBT_INLINE void routing_asr_prop_free(void *p)
-{
- //xbt_dict_t elm = (xbt_dict_t) p;
- //xbt_dict_free(&elm); FIXME: leaking in some case? That's a sometimes double-free with AsCluster::~AsCluster
-}
-
static XBT_INLINE void surf_storage_free(void *r)
{
delete static_cast<simgrid::surf::Storage*>(r);
sg_host_init();
XBT_DEBUG("Add routing levels");
- ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
+ ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib, NULL);
XBT_DEBUG("Add SURF levels");
simgrid::surf::HostImpl::classInit();
#include <stdio.h> /* snprintf */
#include <stdlib.h> /* snprintf */
-#include "src/portable.h" /* to get a working stdarg.h */
+#include "src/portable.h"
#include "src/xbt_modinter.h"
* http://www.ijs.si/software/snprintf/
*/
-#include "xbt/sysdep.h" /* xbt_abort() */
-#include "simgrid_config.h" /* Do we need vasprintf? */
+#include "xbt/sysdep.h" /* xbt_abort() */
+#include "src/internal_config.h" /* Do we need vasprintf? */
#include <stdio.h>
#if !defined(HAVE_VASPRINTF)
/* We have mmap and objdump to handle privatization */
#cmakedefine HAVE_PRIVATIZATION @HAVE_PRIVATIZATION@
-/* Indicates that we have NS3 support */
-#cmakedefine HAVE_NS3 @HAVE_NS3@
-
-/* defines whether Lua bindings must be compiled or not */
-#cmakedefine HAVE_LUA @HAVE_LUA@
-
/* Define to 1 if you have the `makecontext' function. */
#cmakedefine HAVE_MAKECONTEXT @HAVE_MAKECONTEXT@