int test(int argc, char **argv){ MSG_process_sleep(1); XBT_INFO("**** Start test ****"); XBT_INFO("Free after first snapshot"); char *toto = xbt_malloc(5); XBT_INFO("Toto allocated"); void *snap1 = MC_snapshot(); MSG_process_sleep(1); XBT_INFO("First snapshot"); xbt_free(toto); XBT_INFO("Toto free"); void *snap2 = MC_snapshot(); XBT_INFO("Second snapshot"); MSG_process_sleep(1); MC_ignore_stack("snap2", "test"); MC_ignore_stack("snap1", "test"); XBT_INFO("Test result : %d (0 = state equality, 1 = different states)", MC_compare_snapshots(snap1, snap2)); XBT_INFO("**** End test ****"); xbt_abort(); }
/** * \ingroup simix_synchro_management * */ smx_mutex_t simcall_mutex_init(void) { if(!simix_global) { fprintf(stderr,"You must run MSG_init before using MSG\n"); // We can't use xbt_die since we may get there before the initialization xbt_abort(); } return simcall_BODY_mutex_init(); }
int smpi_global_size(void) { char *value = getenv("SMPI_GLOBAL_SIZE"); if (!value) { fprintf(stderr, "Please set env var SMPI_GLOBAL_SIZE to expected number of processes.\n"); xbt_abort(); } return atoi(value); }
char *bvprintf(const char *fmt, va_list ap) { char *res; if (vasprintf(&res, fmt, ap) < 0) { /* Do not want to use xbt_die() here, as it uses the logging * infrastucture and may fail to allocate memory too. */ fprintf(stderr, "bprintf: vasprintf failed. Aborting.\n"); xbt_abort(); } return res; }
void MC_init_dot_output() { dot_output = fopen(_sg_mc_dot_output_file, "w"); if (dot_output == nullptr) { perror("Error open dot output file"); xbt_abort(); } fprintf(dot_output, "digraph graphname{\n fixedsize=true; rankdir=TB; ranksep=.25; edge [fontsize=12]; node [fontsize=10, shape=circle,width=.5 ]; graph [resolution=20, fontsize=10];\n"); }
XBT_PRIVATE std::vector<VmMap> get_memory_map(pid_t pid) { #ifdef __linux__ /* Open the actual process's proc maps file and create the memory_map_t */ /* to be returned. */ char* path = bprintf("/proc/%i/maps", (int) pid); FILE *fp = std::fopen(path, "r"); if(fp == NULL) std::perror("fopen failed"); xbt_assert(fp, "Cannot open %s to investigate the memory map of the process.", path); free(path); setbuf(fp, NULL); std::vector<VmMap> ret; /* Read one line at the time, parse it and add it to the memory map to be returned */ ssize_t read; /* Number of bytes readed */ char* line = NULL; std::size_t n = 0; /* Amount of bytes to read by xbt_getline */ while ((read = xbt_getline(&line, &n, fp)) != -1) { //fprintf(stderr,"%s", line); /* Wipeout the new line character */ line[read - 1] = '\0'; /* Tokenize the line using spaces as delimiters and store each token */ /* in lfields array. We expect 5 tokens/fields */ char* lfields[6]; lfields[0] = strtok(line, " "); int i; for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) { lfields[i] = std::strtok(NULL, " "); } /* Check to see if we got the expected amount of columns */ if (i < 6) xbt_abort(); /* Ok we are good enough to try to get the info we need */ /* First get the start and the end address of the map */ char *tok = std::strtok(lfields[0], "-"); if (tok == NULL) xbt_abort(); VmMap memreg; char *endptr; memreg.start_addr = std::strtoull(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = std::strtok(NULL, "-"); if (tok == NULL) xbt_abort(); memreg.end_addr = std::strtoull(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the permissions flags */ if (std::strlen(lfields[1]) < 4) xbt_abort(); memreg.prot = 0; for (i = 0; i < 3; i++){ switch(lfields[1][i]){ case 'r': memreg.prot |= PROT_READ; break; case 'w': memreg.prot |= PROT_WRITE; break; case 'x': memreg.prot |= PROT_EXEC; break; default: break; } } if (memreg.prot == 0) memreg.prot |= PROT_NONE; if (lfields[1][4] == 'p') memreg.flags |= MAP_PRIVATE; else if (lfields[1][4] == 's') memreg.flags |= MAP_SHARED; /* Get the offset value */ memreg.offset = std::strtoull(lfields[2], &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the device major:minor bytes */ tok = std::strtok(lfields[3], ":"); if (tok == NULL) xbt_abort(); memreg.dev_major = (char) strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = std::strtok(NULL, ":"); if (tok == NULL) xbt_abort(); memreg.dev_minor = (char) std::strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the inode number and make sure that the entire string was a long int */ memreg.inode = strtoul(lfields[4], &endptr, 10); if (*endptr != '\0') xbt_abort(); /* And finally get the pathname */ if (lfields[5]) memreg.pathname = lfields[5]; /* Create space for a new map region in the region's array and copy the */ /* parsed stuff from the temporal memreg variable */ XBT_DEBUG("Found region for %s", !memreg.pathname.empty() ? memreg.pathname.c_str() : "(null)"); ret.push_back(std::move(memreg)); } std::free(line); std::fclose(fp); return ret; #else /* On FreeBSD, kinfo_getvmmap() could be used but mmap() support is disabled anyway. */ xbt_die("Could not get memory map from process %lli", (long long int) pid); #endif }
/* default __ex_terminate callback function */ void __xbt_ex_terminate_default(xbt_ex_t * e) { xbt_ex_display(e); xbt_abort(); }
memory_map_t get_memory_map(void) { FILE *fp; /* File pointer to process's proc maps file */ char *line = NULL; /* Temporal storage for each line that is readed */ ssize_t read; /* Number of bytes readed */ size_t n = 0; /* Amount of bytes to read by xbt_getline */ memory_map_t ret = NULL; /* The memory map to return */ /* The following variables are used during the parsing of the file "maps" */ s_map_region_t memreg; /* temporal map region used for creating the map */ char *lfields[6], *tok, *endptr; int i; /* Open the actual process's proc maps file and create the memory_map_t */ /* to be returned. */ fp = fopen("/proc/self/maps", "r"); if(fp == NULL) perror("fopen failed"); xbt_assert(fp, "Cannot open /proc/self/maps to investigate the memory map of the process. Please report this bug."); setbuf(fp, NULL); ret = xbt_new0(s_memory_map_t, 1); /* Read one line at the time, parse it and add it to the memory map to be returned */ while ((read = xbt_getline(&line, &n, fp)) != -1) { //fprintf(stderr,"%s", line); /* Wipeout the new line character */ line[read - 1] = '\0'; /* Tokenize the line using spaces as delimiters and store each token */ /* in lfields array. We expect 5 tokens/fields */ lfields[0] = strtok(line, " "); for (i = 1; i < 6 && lfields[i - 1] != NULL; i++) { lfields[i] = strtok(NULL, " "); } /* Check to see if we got the expected amount of columns */ if (i < 6) xbt_abort(); /* Ok we are good enough to try to get the info we need */ /* First get the start and the end address of the map */ tok = strtok(lfields[0], "-"); if (tok == NULL) xbt_abort(); memreg.start_addr = (void *) strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = strtok(NULL, "-"); if (tok == NULL) xbt_abort(); memreg.end_addr = (void *) strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the permissions flags */ if (strlen(lfields[1]) < 4) xbt_abort(); memreg.prot = 0; for (i = 0; i < 3; i++){ switch(lfields[1][i]){ case 'r': memreg.prot |= PROT_READ; break; case 'w': memreg.prot |= PROT_WRITE; break; case 'x': memreg.prot |= PROT_EXEC; break; default: break; } } if (memreg.prot == 0) memreg.prot |= PROT_NONE; if (lfields[1][4] == 'p') memreg.flags |= MAP_PRIVATE; else if (lfields[1][4] == 's') memreg.flags |= MAP_SHARED; /* Get the offset value */ memreg.offset = (void *) strtoul(lfields[2], &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the device major:minor bytes */ tok = strtok(lfields[3], ":"); if (tok == NULL) xbt_abort(); memreg.dev_major = (char) strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = strtok(NULL, ":"); if (tok == NULL) xbt_abort(); memreg.dev_minor = (char) strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the inode number and make sure that the entire string was a long int */ memreg.inode = strtoul(lfields[4], &endptr, 10); if (*endptr != '\0') xbt_abort(); /* And finally get the pathname */ memreg.pathname = xbt_strdup(lfields[5]); /* Create space for a new map region in the region's array and copy the */ /* parsed stuff from the temporal memreg variable */ ret->regions = xbt_realloc(ret->regions, sizeof(memreg) * (ret->mapsize + 1)); memcpy(ret->regions + ret->mapsize, &memreg, sizeof(memreg)); ret->mapsize++; } free(line); fclose(fp); return ret; }
static int xbt_log_layout_format_doit(xbt_log_layout_t l, xbt_log_event_t ev, const char *msg_fmt) { char *p = ev->buffer; int rem_size = ev->buffer_size; int precision = -1; int length = -1; char *q; for (q = l->data ; *q != '\0' ; q++) { if (*q == '%') { q++; handle_modifier: switch (*q) { case '\0': fprintf(stderr, "Layout format (%s) ending with %%\n", (char *)l->data); xbt_abort(); case '%': *p = '%'; check_overflow(1); break; case 'n': /* platform-dependant line separator; LOG4J compliant */ *p = '\n'; check_overflow(1); break; case 'e': /* plain space; SimGrid extension */ *p = ' '; check_overflow(1); break; case '.': /* precision specifier */ precision = strtol(q + 1, &q, 10); goto handle_modifier; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* length modifier */ length = strtol(q, &q, 10); goto handle_modifier; case 'c': /* category name; LOG4J compliant should accept a precision postfix to show the hierarchy */ show_string(ev->cat->name); break; case 'p': /* priority name; LOG4J compliant */ show_string(xbt_log_priority_names[ev->priority]); break; case 'h': /* host name; SimGrid extension */ show_string(SIMIX_host_self_get_name()); break; case 't': /* thread name; LOG4J compliant */ show_string(SIMIX_process_self_get_name()); break; case 'P': /* process name; SimGrid extension */ show_string(xbt_procname()); break; case 'i': /* process PID name; SimGrid extension */ show_int(xbt_getpid()); break; case 'F': /* file name; LOG4J compliant */ show_string(ev->fileName); break; case 'l': { /* location; LOG4J compliant */ int len, sz; set_sz_from_precision(); len = snprintf(p, sz, "%s:%d", ev->fileName, ev->lineNum); check_overflow(MIN(sz, len)); break; } case 'L': /* line number; LOG4J compliant */ show_int(ev->lineNum); break; case 'M': /* method (ie, function) name; LOG4J compliant */ show_string(ev->functionName); break; case 'b': /* backtrace; called %throwable in LOG4J */ case 'B': /* short backtrace; called %throwable{short} in LOG4J */ // TODO, backtrace #if 0 && HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE) { xbt_ex_t e(""); e.used = backtrace((void **) e.bt, XBT_BACKTRACE_SIZE); e.bt_strings = NULL; xbt_ex_setup_backtrace(&e); if (*q == 'B') { show_string(e.bt_strings[1] + 8); } else { xbt_strbuff_t buff = xbt_strbuff_new(); int i; xbt_strbuff_append(buff, e.bt_strings[1] + 8); for (i = 2; i < e.used; i++) { xbt_strbuff_append(buff, "\n"); xbt_strbuff_append(buff, e.bt_strings[i] + 8); } show_string(buff->data); xbt_strbuff_free(buff); } } #else show_string("(no backtrace on this arch)"); #endif break; case 'd': /* date; LOG4J compliant */ show_double(surf_get_clock()); break; case 'r': /* application age; LOG4J compliant */ show_double(surf_get_clock() - format_begin_of_time); break; case 'm': { /* user-provided message; LOG4J compliant */ int len, sz; set_sz_from_precision(); len = vsnprintf(p, sz, msg_fmt, ev->ap); check_overflow(MIN(sz, len)); break; } default: fprintf(stderr, ERRMSG, *q, (char *)l->data); xbt_abort(); } } else { *p = *q; check_overflow(1); } } *p = '\0'; return 1; }
/** * \todo This function contains many cases that do not allow for a * recovery. Currently, xbt_abort() is called but we should * much rather die with the specific reason so that it's easier * to find out what's going on. */ XBT_PRIVATE std::vector<VmMap> get_memory_map(pid_t pid) { std::vector<VmMap> ret; #ifdef __linux__ /* Open the actual process's proc maps file and create the memory_map_t */ /* to be returned. */ char* path = bprintf("/proc/%i/maps", (int) pid); FILE *fp = std::fopen(path, "r"); if (fp == nullptr) { std::perror("fopen failed"); xbt_die("Cannot open %s to investigate the memory map of the process.", path); } free(path); setbuf(fp, nullptr); /* Read one line at the time, parse it and add it to the memory map to be returned */ ssize_t read; /* Number of bytes readed */ char* line = nullptr; std::size_t n = 0; /* Amount of bytes to read by xbt_getline */ while ((read = xbt_getline(&line, &n, fp)) != -1) { /** * The lines that we read have this format: (This is just an example) * 00602000-00603000 rw-p 00002000 00:28 1837264 <complete-path-to-file> */ //fprintf(stderr,"%s", line); /* Wipeout the new line character */ line[read - 1] = '\0'; /* Tokenize the line using spaces as delimiters and store each token in lfields array. We expect 5 tokens for 6 fields */ char* lfields[6]; lfields[0] = strtok(line, " "); int i; for (i = 1; i < 6 && lfields[i - 1] != nullptr; i++) { lfields[i] = std::strtok(nullptr, " "); } /* Check to see if we got the expected amount of columns */ if (i < 6) xbt_die("The memory map apparently only supplied less than 6 columns. Recovery impossible."); /* Ok we are good enough to try to get the info we need */ /* First get the start and the end address of the map */ char *tok = std::strtok(lfields[0], "-"); if (tok == nullptr) xbt_die("Start and end address of the map are not concatenated by a hyphen (-). Recovery impossible."); VmMap memreg; char *endptr; memreg.start_addr = std::strtoull(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = std::strtok(nullptr, "-"); if (tok == nullptr) xbt_abort(); memreg.end_addr = std::strtoull(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the permissions flags */ if (std::strlen(lfields[1]) < 4) xbt_abort(); memreg.prot = 0; for (i = 0; i < 3; i++){ switch(lfields[1][i]){ case 'r': memreg.prot |= PROT_READ; break; case 'w': memreg.prot |= PROT_WRITE; break; case 'x': memreg.prot |= PROT_EXEC; break; default: break; } } if (memreg.prot == 0) memreg.prot |= PROT_NONE; if (lfields[1][3] == 'p') { memreg.flags |= MAP_PRIVATE; } else { memreg.flags |= MAP_SHARED; if (lfields[1][3] != 's') XBT_WARN("The protection is neither 'p' (private) nor 's' (shared) but '%s'. Let's assume shared, as on b0rken win-ubuntu systems.\nFull line: %s\n", lfields[1], line); } /* Get the offset value */ memreg.offset = std::strtoull(lfields[2], &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the device major:minor bytes */ tok = std::strtok(lfields[3], ":"); if (tok == nullptr) xbt_abort(); memreg.dev_major = (char) strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = std::strtok(nullptr, ":"); if (tok == nullptr) xbt_abort(); memreg.dev_minor = (char) std::strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the inode number and make sure that the entire string was a long int */ memreg.inode = strtoul(lfields[4], &endptr, 10); if (*endptr != '\0') xbt_abort(); /* And finally get the pathname */ if (lfields[5]) memreg.pathname = lfields[5]; /* Create space for a new map region in the region's array and copy the */ /* parsed stuff from the temporal memreg variable */ XBT_DEBUG("Found region for %s", !memreg.pathname.empty() ? memreg.pathname.c_str() : "(null)"); ret.push_back(std::move(memreg)); } std::free(line); std::fclose(fp); #elif defined __FreeBSD__ struct procstat *prstat; struct kinfo_proc *proc; struct kinfo_vmentry *vmentries; unsigned int cnt; if ((prstat = procstat_open_sysctl()) == NULL) { std::perror("procstat_open_sysctl failed"); xbt_die("Cannot access kernel state information"); } if ((proc = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt)) == NULL) { std::perror("procstat_open_sysctl failed"); xbt_die("Cannot access process information"); } if ((vmentries = procstat_getvmmap(prstat, proc, &cnt)) == NULL) { std::perror("procstat_getvmmap failed"); xbt_die("Cannot access process memory mappings"); } for (unsigned int i = 0; i < cnt; i++) { VmMap memreg; /* Addresses */ memreg.start_addr = vmentries[i].kve_start; memreg.end_addr = vmentries[i].kve_end; /* Permissions */ memreg.prot = PROT_NONE; if (vmentries[i].kve_protection & KVME_PROT_READ) memreg.prot |= PROT_READ; if (vmentries[i].kve_protection & KVME_PROT_WRITE) memreg.prot |= PROT_WRITE; if (vmentries[i].kve_protection & KVME_PROT_EXEC) memreg.prot |= PROT_EXEC; /* Private (copy-on-write) or shared? */ if (vmentries[i].kve_flags & KVME_FLAG_COW) memreg.flags |= MAP_PRIVATE; else memreg.flags |= MAP_SHARED; /* Offset */ memreg.offset = vmentries[i].kve_offset; /* Device : not sure this can be mapped to something outside of Linux? */ memreg.dev_major = 0; memreg.dev_minor = 0; /* Inode */ memreg.inode = vmentries[i].kve_vn_fileid; /* * Path. Linuxize result by giving an anonymous mapping a path from * the previous mapping, provided previous is vnode and has a path, * and mark the stack. */ if (vmentries[i].kve_path[0] != '\0') memreg.pathname = vmentries[i].kve_path; else if (vmentries[i].kve_type == KVME_TYPE_DEFAULT && vmentries[i-1].kve_type == KVME_TYPE_VNODE && vmentries[i-1].kve_path[0] != '\0') memreg.pathname = vmentries[i-1].kve_path; else if (vmentries[i].kve_type == KVME_TYPE_DEFAULT && vmentries[i].kve_flags & KVME_FLAG_GROWS_DOWN) memreg.pathname = "[stack]"; /* * One last dirty modification: remove write permission from shared * libraries private clean pages. This is necessary because simgrid * later identifies mappings based on the permissions that are expected * when running the Linux kernel. */ if (vmentries[i].kve_type == KVME_TYPE_VNODE && ! (vmentries[i].kve_flags & KVME_FLAG_NEEDS_COPY)) memreg.prot &= ~PROT_WRITE; ret.push_back(std::move(memreg)); } procstat_freevmmap(prstat, vmentries); procstat_freeprocs(prstat, proc); procstat_close(prstat); #else xbt_die("Could not get memory map from process %lli", (long long int) pid); #endif return ret; }